* Re: [PATCH 2/4] serio: Add pnp_id to struct serio
From: Dmitry Torokhov @ 2014-04-09 18:06 UTC (permalink / raw)
To: Hans de Goede; +Cc: Benjamin Tissoires, Peter Hutterer, linux-input
In-Reply-To: <1397052181-22768-2-git-send-email-hdegoede@redhat.com>
Hi Hans,
On Wed, Apr 09, 2014 at 04:02:59PM +0200, Hans de Goede wrote:
> Serio device drivers need access to the pnp_id of the serio port, windows
> drivers bind by the pnp-id and some drivers need to know the exact pnp-id
> used so they know exactly with which hardware model / revision they are
> dealing with.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
> include/linux/serio.h | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/include/linux/serio.h b/include/linux/serio.h
> index 9f779c7..6532440 100644
> --- a/include/linux/serio.h
> +++ b/include/linux/serio.h
> @@ -16,6 +16,7 @@
> #include <linux/mutex.h>
> #include <linux/device.h>
> #include <linux/mod_devicetable.h>
> +#include <linux/pnp.h>
> #include <uapi/linux/serio.h>
>
> struct serio {
> @@ -28,6 +29,7 @@ struct serio {
> bool manual_bind;
>
> struct serio_device_id id;
> + struct pnp_id *pnp_id;
Why do we need this if we are already adding generic 'firmware_id'
attribute?
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v4 7/7] HID: sony: Add blink support to the Sixaxis and DualShock 4 LEDs
From: Frank Praznik @ 2014-04-09 17:41 UTC (permalink / raw)
To: simon, Frank Praznik; +Cc: HID CORE LAYER, Jiri Kosina
In-Reply-To: <5ab597fe6a7cc937a8d41df6df7adc47.squirrel@mungewell.org>
On 4/9/2014 01:51, simon@mungewell.org wrote:
> Unfortunately I was unable to find the 'led chaining' code I mentioned. I
> guess it has been lost to the sands of time....
>
>>> 3rd Party Intec - Was unable to get any controlled blinking. As
>>> previously
>>> mentioned all leds flash (automatic, as if first plugged in) whenever
>>> all
>>> leds are turned off.
>>> I can control all leds in a static on/off mode, but can't set any
>>> blinking/timer behaviour
>> It sounds like this controller just doesn't implement all of the
>> behavior of the official controller. I'm not sure how to fix it if it's
>> not obeying the instructions in valid output reports and I don't have
>> one to test personally. Do the lights flash properly when the
>> controller is used with a PS3?
> I was able to patch the code so that I could turn all LEDs off my Intec
> controller, see attached. Tested this against the Intec and the SixAxis.
Thanks for taking care of this. I'll add it to the v5 series when I
send it in a couple of days.
>
> I was not able to make the LEDs flash in a controlled fashion, so you
> might be right about the controller not working properly - although my
> comments in python script suggests I did have something going.... must be
> missing a snippet of info.
>
>
> I also found that on the SixAxis, when I reported that I had to set 1st
> LED off before I could set it on.... this only applies when the controller
> was off and then plugged into USB. At this point the LEDs are slow
> flashing, and the 'brightness' reports as 1 (driver code only writes to
> device if value is changed).
>
> If the device was already on (LEDs flashing) then only the 1st LED is set
> on plug in, and I can turn LEDs off/on straight away.
Yeah, the controller overriding user settings and flashing by itself
until the PS button is pushed is a particularly annoying aspect of the
Sixaxis on USB and there is no perfect way to handle it. I wish that I
could just submit a report from within the driver the first time the PS
button is pressed to restore the LED state, but that could mess with
hidraw applications. The next-best solution would probably be to not
filter redundant LED state settings for Sixaxis controllers on USB.
This way, userland can stop the flashing without having to toggle an LED
on/off or off/on if they are already set to the desired state. I'll
make the change for v5.
Thanks again for all of the testing :)
^ permalink raw reply
* Re: [PATCH] HID: rmi: do not stop the device at the end of probe
From: Jiri Kosina @ 2014-04-09 15:14 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Andrew Duggan, Christopher Heiny, linux-input, linux-kernel
In-Reply-To: <1397055694-6312-1-git-send-email-benjamin.tissoires@redhat.com>
On Wed, 9 Apr 2014, Benjamin Tissoires wrote:
> Well, this is embarrassing, if the device is stopped at the end of probe,
> we get into big troubles (it even oopses my kernel).
>
> This was a leftover of an attempt to be smart when sending the patch,
> I deeply apologies.
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
>
> Hi Jiri,
>
> well, first thanks for having integrating hid-rmi in your for 3.16 branch.
>
> While backporting it to 3.13 so Fedora can get it, I noticed a tiny difference
> (besides formatting) between the version I submitted and the one I asked people
> to test...
>
> ...facepalm.
Well, I missed that as well when reviewing it. Good catch, now queued on
top of previous one. Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* [PATCH] HID: rmi: do not stop the device at the end of probe
From: Benjamin Tissoires @ 2014-04-09 15:01 UTC (permalink / raw)
To: Andrew Duggan, Christopher Heiny, Jiri Kosina, linux-input,
linux-kernel
Well, this is embarrassing, if the device is stopped at the end of probe,
we get into big troubles (it even oopses my kernel).
This was a leftover of an attempt to be smart when sending the patch,
I deeply apologies.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
Hi Jiri,
well, first thanks for having integrating hid-rmi in your for 3.16 branch.
While backporting it to 3.13 so Fedora can get it, I noticed a tiny difference
(besides formatting) between the version I submitted and the one I asked people
to test...
...facepalm.
Cheers,
Benjamin
drivers/hid/hid-rmi.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index 699d631..7da9509 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -848,7 +848,6 @@ static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id)
return -EIO;
}
- hid_hw_stop(hdev);
return 0;
}
--
1.9.0
^ permalink raw reply related
* Re: [PATCH] HID: rmi: introduce RMI driver for Synaptics touchpads
From: Jiri Kosina @ 2014-04-09 14:03 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Andrew Duggan, Christopher Heiny, linux-input, linux-kernel
In-Reply-To: <1396892373-3330-1-git-send-email-benjamin.tissoires@redhat.com>
On Mon, 7 Apr 2014, Benjamin Tissoires wrote:
> This driver add support for RMI4 over USB or I2C.
> The current state is that it uses its own RMI4 implementation, but once
> RMI4 is merged upstream, the driver will be a transport driver for the
> RMI4 library.
Queuing for 3.16, thanks.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* [PATCH 4/4] synaptices: Report INPUT_PROP_TOPBUTTONPAD property for touchpads with top buttonareas
From: Hans de Goede @ 2014-04-09 14:03 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Benjamin Tissoires, Peter Hutterer, linux-input, Hans de Goede
In-Reply-To: <1397052181-22768-1-git-send-email-hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/input/mouse/synaptics.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index d8d49d1..4637cc7 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -118,6 +118,16 @@ void synaptics_reset(struct psmouse *psmouse)
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
+static const char *topbuttonpad_pnp_ids[] = {
+ "LEN0033", /* Helix */
+ "LEN0034", /* T540, X1 Carbon 2nd */
+ "LEN0035", /* X240 */
+ "LEN0036", /* T440 */
+ "LEN0042", /* Yoga */
+ "LEN2004", /* L440 */
+ NULL
+};
+
/*****************************************************************************
* Synaptics communications functions
****************************************************************************/
@@ -1255,8 +1265,10 @@ static void set_abs_position_params(struct input_dev *dev,
input_abs_set_res(dev, y_code, priv->y_res);
}
-static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
+static void set_input_params(struct psmouse *psmouse,
+ struct synaptics_data *priv)
{
+ struct input_dev *dev = psmouse->dev;
int i;
/* Things that apply to both modes */
@@ -1325,6 +1337,15 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
+ /* See if this buttonpad has a top button area */
+ for (i = 0; topbuttonpad_pnp_ids[i]; i++) {
+ if (compare_pnp_id(psmouse->ps2dev.serio->pnp_id,
+ topbuttonpad_pnp_ids[i])) {
+ __set_bit(INPUT_PROP_TOPBUTTONPAD,
+ dev->propbit);
+ break;
+ }
+ }
/* Clickpads report only left button */
__clear_bit(BTN_RIGHT, dev->keybit);
__clear_bit(BTN_MIDDLE, dev->keybit);
@@ -1593,7 +1614,7 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
priv->capabilities, priv->ext_cap, priv->ext_cap_0c,
priv->board_id, priv->firmware_id);
- set_input_params(psmouse->dev, priv);
+ set_input_params(psmouse, priv);
/*
* Encode touchpad model so that it can be used to set
--
1.9.0
^ permalink raw reply related
* [PATCH 3/4] input/serio/8042_pnp: set serio->pnp_id for pnp instantiated 8042 ports
From: Hans de Goede @ 2014-04-09 14:03 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Benjamin Tissoires, Peter Hutterer, linux-input, Hans de Goede
In-Reply-To: <1397052181-22768-1-git-send-email-hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/input/serio/i8042-x86ia64io.h | 4 ++++
drivers/input/serio/i8042.c | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 2416c74..1d2e13f 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -725,6 +725,8 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
if (pnp_irq_valid(dev,0))
i8042_pnp_kbd_irq = pnp_irq(dev, 0);
+ i8042_kbd_pnp_id = dev->id;
+
strlcpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
if (strlen(pnp_dev_name(dev))) {
strlcat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
@@ -751,6 +753,8 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
if (pnp_irq_valid(dev, 0))
i8042_pnp_aux_irq = pnp_irq(dev, 0);
+ i8042_aux_pnp_id = dev->id;
+
strlcpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
if (strlen(pnp_dev_name(dev))) {
strlcat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 3807c3e..4a3fdf4 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -89,6 +89,8 @@ MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off");
static bool i8042_bypass_aux_irq_test;
static char i8042_kbd_firmware_id[128];
static char i8042_aux_firmware_id[128];
+static struct pnp_id *i8042_kbd_pnp_id;
+static struct pnp_id *i8042_aux_pnp_id;
#include "i8042.h"
@@ -1217,6 +1219,7 @@ static int __init i8042_create_kbd_port(void)
serio->stop = i8042_stop;
serio->close = i8042_port_close;
serio->port_data = port;
+ serio->pnp_id = i8042_kbd_pnp_id;
serio->dev.parent = &i8042_platform_device->dev;
strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name));
strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
@@ -1246,6 +1249,7 @@ static int __init i8042_create_aux_port(int idx)
serio->port_data = port;
serio->dev.parent = &i8042_platform_device->dev;
if (idx < 0) {
+ serio->pnp_id = i8042_aux_pnp_id;
strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name));
strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
strlcpy(serio->firmware_id, i8042_aux_firmware_id,
--
1.9.0
^ permalink raw reply related
* [PATCH 2/4] serio: Add pnp_id to struct serio
From: Hans de Goede @ 2014-04-09 14:02 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Benjamin Tissoires, Peter Hutterer, linux-input, Hans de Goede
In-Reply-To: <1397052181-22768-1-git-send-email-hdegoede@redhat.com>
Serio device drivers need access to the pnp_id of the serio port, windows
drivers bind by the pnp-id and some drivers need to know the exact pnp-id
used so they know exactly with which hardware model / revision they are
dealing with.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
include/linux/serio.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 9f779c7..6532440 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -16,6 +16,7 @@
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/mod_devicetable.h>
+#include <linux/pnp.h>
#include <uapi/linux/serio.h>
struct serio {
@@ -28,6 +29,7 @@ struct serio {
bool manual_bind;
struct serio_device_id id;
+ struct pnp_id *pnp_id;
spinlock_t lock; /* protects critical sections from port's interrupt handler */
--
1.9.0
^ permalink raw reply related
* [PATCH 1/4] uapi/input.h: Add INPUT_PROP_TOPBUTTONPAD device property
From: Hans de Goede @ 2014-04-09 14:02 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Benjamin Tissoires, Peter Hutterer, linux-input, Hans de Goede
On some newer laptops with a trackpoint the physical buttons for the
trackpoint have been removed to allow for a larger touchpad. On these
laptops the buttonpad has clearly marked areas on the top which are to be
used as trackpad buttons.
Users of the event device-node need to know about this, so that they can
properly interpret BTN_LEFT events as being a left / right / middle click
depending on where on the button pad the clicking finger is.
This commits adds a INPUT_PROP_TOPBUTTONPAD device property which drivers
for such buttonpads will use to signal to the user that this buttonpad not
only has the normal bottom button area, but also a top button area.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
include/uapi/linux/input.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index bd24470..f484952 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -164,6 +164,7 @@ struct input_keymap_entry {
#define INPUT_PROP_DIRECT 0x01 /* direct input devices */
#define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */
#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */
+#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
#define INPUT_PROP_MAX 0x1f
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
--
1.9.0
^ permalink raw reply related
* [PATCH 24/24] Replace ff-memless with ff-memless-next
From: Michal Malý @ 2014-04-09 11:36 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Replace ff-memless with ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/input/Kconfig | 13 +-
drivers/input/Makefile | 1 -
drivers/input/ff-memless.c | 547 ---------------------------------------------
include/linux/input.h | 3 -
4 files changed, 1 insertion(+), 563 deletions(-)
delete mode 100644 drivers/input/ff-memless.c
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 3780962..061ae3c 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -25,7 +25,7 @@ config INPUT
if INPUT
-config INPUT_FF_MEMLESS
+config INPUT_FF_MEMLESS_NEXT
tristate "Support for memoryless force-feedback devices"
help
Say Y here if you have memoryless force-feedback input device
@@ -36,17 +36,6 @@ config INPUT_FF_MEMLESS
If unsure, say N.
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
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index b4f11f5..f7ae055 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -7,7 +7,6 @@
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
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
deleted file mode 100644
index 74c0d8c..0000000
--- a/drivers/input/ff-memless.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * Force feedback support for memoryless devices
- *
- * Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com>
- * Copyright (c) 2006 Dmitry Torokhov <dtor@mail.ru>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* #define DEBUG */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-#include <linux/jiffies.h>
-#include <linux/fixp-arith.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Anssi Hannula <anssi.hannula@gmail.com>");
-MODULE_DESCRIPTION("Force feedback support for memoryless devices");
-
-/* Number of effects handled with memoryless devices */
-#define FF_MEMLESS_EFFECTS 16
-
-/* Envelope update interval in ms */
-#define FF_ENVELOPE_INTERVAL 50
-
-#define FF_EFFECT_STARTED 0
-#define FF_EFFECT_PLAYING 1
-#define FF_EFFECT_ABORTING 2
-
-struct ml_effect_state {
- struct ff_effect *effect;
- unsigned long flags; /* effect state (STARTED, PLAYING, etc) */
- int count; /* loop count of the effect */
- unsigned long play_at; /* start time */
- unsigned long stop_at; /* stop time */
- unsigned long adj_at; /* last time the effect was sent */
-};
-
-struct ml_device {
- void *private;
- struct ml_effect_state states[FF_MEMLESS_EFFECTS];
- int gain;
- struct timer_list timer;
- struct input_dev *dev;
-
- int (*play_effect)(struct input_dev *dev, void *data,
- struct ff_effect *effect);
-};
-
-static const struct ff_envelope *get_envelope(const struct ff_effect *effect)
-{
- static const struct ff_envelope empty_envelope;
-
- switch (effect->type) {
- case FF_PERIODIC:
- return &effect->u.periodic.envelope;
-
- case FF_CONSTANT:
- return &effect->u.constant.envelope;
-
- default:
- return &empty_envelope;
- }
-}
-
-/*
- * Check for the next time envelope requires an update on memoryless devices
- */
-static unsigned long calculate_next_time(struct ml_effect_state *state)
-{
- const struct ff_envelope *envelope = get_envelope(state->effect);
- unsigned long attack_stop, fade_start, next_fade;
-
- if (envelope->attack_length) {
- attack_stop = state->play_at +
- msecs_to_jiffies(envelope->attack_length);
- if (time_before(state->adj_at, attack_stop))
- return state->adj_at +
- msecs_to_jiffies(FF_ENVELOPE_INTERVAL);
- }
-
- if (state->effect->replay.length) {
- if (envelope->fade_length) {
- /* check when fading should start */
- fade_start = state->stop_at -
- msecs_to_jiffies(envelope->fade_length);
-
- if (time_before(state->adj_at, fade_start))
- return fade_start;
-
- /* already fading, advance to next checkpoint */
- next_fade = state->adj_at +
- msecs_to_jiffies(FF_ENVELOPE_INTERVAL);
- if (time_before(next_fade, state->stop_at))
- return next_fade;
- }
-
- return state->stop_at;
- }
-
- return state->play_at;
-}
-
-static void ml_schedule_timer(struct ml_device *ml)
-{
- struct ml_effect_state *state;
- unsigned long now = jiffies;
- unsigned long earliest = 0;
- unsigned long next_at;
- int events = 0;
- int i;
-
- pr_debug("calculating next timer\n");
-
- for (i = 0; i < FF_MEMLESS_EFFECTS; i++) {
-
- state = &ml->states[i];
-
- if (!test_bit(FF_EFFECT_STARTED, &state->flags))
- continue;
-
- if (test_bit(FF_EFFECT_PLAYING, &state->flags))
- next_at = calculate_next_time(state);
- else
- next_at = state->play_at;
-
- if (time_before_eq(now, next_at) &&
- (++events == 1 || time_before(next_at, earliest)))
- earliest = next_at;
- }
-
- if (!events) {
- pr_debug("no actions\n");
- del_timer(&ml->timer);
- } else {
- pr_debug("timer set\n");
- mod_timer(&ml->timer, earliest);
- }
-}
-
-/*
- * Apply an envelope to a value
- */
-static int apply_envelope(struct ml_effect_state *state, int value,
- struct ff_envelope *envelope)
-{
- struct ff_effect *effect = state->effect;
- unsigned long now = jiffies;
- int time_from_level;
- int time_of_envelope;
- int envelope_level;
- int difference;
-
- if (envelope->attack_length &&
- time_before(now,
- state->play_at + msecs_to_jiffies(envelope->attack_length))) {
- pr_debug("value = 0x%x, attack_level = 0x%x\n",
- value, envelope->attack_level);
- time_from_level = jiffies_to_msecs(now - state->play_at);
- time_of_envelope = envelope->attack_length;
- envelope_level = min_t(u16, envelope->attack_level, 0x7fff);
-
- } else if (envelope->fade_length && effect->replay.length &&
- time_after(now,
- state->stop_at - msecs_to_jiffies(envelope->fade_length)) &&
- time_before(now, state->stop_at)) {
- time_from_level = jiffies_to_msecs(state->stop_at - now);
- time_of_envelope = envelope->fade_length;
- envelope_level = min_t(u16, envelope->fade_level, 0x7fff);
- } else
- return value;
-
- difference = abs(value) - envelope_level;
-
- pr_debug("difference = %d\n", difference);
- pr_debug("time_from_level = 0x%x\n", time_from_level);
- pr_debug("time_of_envelope = 0x%x\n", time_of_envelope);
-
- difference = difference * time_from_level / time_of_envelope;
-
- pr_debug("difference = %d\n", difference);
-
- return value < 0 ?
- -(difference + envelope_level) : (difference + envelope_level);
-}
-
-/*
- * Return the type the effect has to be converted into (memless devices)
- */
-static int get_compatible_type(struct ff_device *ff, int effect_type)
-{
-
- if (test_bit(effect_type, ff->ffbit))
- return effect_type;
-
- if (effect_type == FF_PERIODIC && test_bit(FF_RUMBLE, ff->ffbit))
- return FF_RUMBLE;
-
- pr_err("invalid type in get_compatible_type()\n");
-
- return 0;
-}
-
-/*
- * Only left/right direction should be used (under/over 0x8000) for
- * forward/reverse motor direction (to keep calculation fast & simple).
- */
-static u16 ml_calculate_direction(u16 direction, u16 force,
- u16 new_direction, u16 new_force)
-{
- if (!force)
- return new_direction;
- if (!new_force)
- return direction;
- return (((u32)(direction >> 1) * force +
- (new_direction >> 1) * new_force) /
- (force + new_force)) << 1;
-}
-
-/*
- * Combine two effects and apply gain.
- */
-static void ml_combine_effects(struct ff_effect *effect,
- struct ml_effect_state *state,
- int gain)
-{
- struct ff_effect *new = state->effect;
- unsigned int strong, weak, i;
- int x, y;
- fixp_t level;
-
- switch (new->type) {
- case FF_CONSTANT:
- i = new->direction * 360 / 0xffff;
- level = fixp_new16(apply_envelope(state,
- new->u.constant.level,
- &new->u.constant.envelope));
- x = fixp_mult(fixp_sin(i), level) * gain / 0xffff;
- y = fixp_mult(-fixp_cos(i), level) * gain / 0xffff;
- /*
- * here we abuse ff_ramp to hold x and y of constant force
- * If in future any driver wants something else than x and y
- * in s8, this should be changed to something more generic
- */
- effect->u.ramp.start_level =
- clamp_val(effect->u.ramp.start_level + x, -0x80, 0x7f);
- effect->u.ramp.end_level =
- clamp_val(effect->u.ramp.end_level + y, -0x80, 0x7f);
- break;
-
- case FF_RUMBLE:
- strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff;
- weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff;
-
- if (effect->u.rumble.strong_magnitude + strong)
- effect->direction = ml_calculate_direction(
- effect->direction,
- effect->u.rumble.strong_magnitude,
- new->direction, strong);
- else if (effect->u.rumble.weak_magnitude + weak)
- effect->direction = ml_calculate_direction(
- effect->direction,
- effect->u.rumble.weak_magnitude,
- new->direction, weak);
- else
- effect->direction = 0;
- effect->u.rumble.strong_magnitude =
- min(strong + effect->u.rumble.strong_magnitude,
- 0xffffU);
- effect->u.rumble.weak_magnitude =
- min(weak + effect->u.rumble.weak_magnitude, 0xffffU);
- break;
-
- case FF_PERIODIC:
- i = apply_envelope(state, abs(new->u.periodic.magnitude),
- &new->u.periodic.envelope);
-
- /* here we also scale it 0x7fff => 0xffff */
- i = i * gain / 0x7fff;
-
- if (effect->u.rumble.strong_magnitude + i)
- effect->direction = ml_calculate_direction(
- effect->direction,
- effect->u.rumble.strong_magnitude,
- new->direction, i);
- else
- effect->direction = 0;
- effect->u.rumble.strong_magnitude =
- min(i + effect->u.rumble.strong_magnitude, 0xffffU);
- effect->u.rumble.weak_magnitude =
- min(i + effect->u.rumble.weak_magnitude, 0xffffU);
- break;
-
- default:
- pr_err("invalid type in ml_combine_effects()\n");
- break;
- }
-
-}
-
-
-/*
- * Because memoryless devices have only one effect per effect type active
- * at one time we have to combine multiple effects into one
- */
-static int ml_get_combo_effect(struct ml_device *ml,
- unsigned long *effect_handled,
- struct ff_effect *combo_effect)
-{
- struct ff_effect *effect;
- struct ml_effect_state *state;
- int effect_type;
- int i;
-
- memset(combo_effect, 0, sizeof(struct ff_effect));
-
- for (i = 0; i < FF_MEMLESS_EFFECTS; i++) {
- if (__test_and_set_bit(i, effect_handled))
- continue;
-
- state = &ml->states[i];
- effect = state->effect;
-
- if (!test_bit(FF_EFFECT_STARTED, &state->flags))
- continue;
-
- if (time_before(jiffies, state->play_at))
- continue;
-
- /*
- * here we have started effects that are either
- * currently playing (and may need be aborted)
- * or need to start playing.
- */
- effect_type = get_compatible_type(ml->dev->ff, effect->type);
- if (combo_effect->type != effect_type) {
- if (combo_effect->type != 0) {
- __clear_bit(i, effect_handled);
- continue;
- }
- combo_effect->type = effect_type;
- }
-
- if (__test_and_clear_bit(FF_EFFECT_ABORTING, &state->flags)) {
- __clear_bit(FF_EFFECT_PLAYING, &state->flags);
- __clear_bit(FF_EFFECT_STARTED, &state->flags);
- } else if (effect->replay.length &&
- time_after_eq(jiffies, state->stop_at)) {
-
- __clear_bit(FF_EFFECT_PLAYING, &state->flags);
-
- if (--state->count <= 0) {
- __clear_bit(FF_EFFECT_STARTED, &state->flags);
- } else {
- state->play_at = jiffies +
- msecs_to_jiffies(effect->replay.delay);
- state->stop_at = state->play_at +
- msecs_to_jiffies(effect->replay.length);
- }
- } else {
- __set_bit(FF_EFFECT_PLAYING, &state->flags);
- state->adj_at = jiffies;
- ml_combine_effects(combo_effect, state, ml->gain);
- }
- }
-
- return combo_effect->type != 0;
-}
-
-static void ml_play_effects(struct ml_device *ml)
-{
- struct ff_effect effect;
- DECLARE_BITMAP(handled_bm, FF_MEMLESS_EFFECTS);
-
- memset(handled_bm, 0, sizeof(handled_bm));
-
- while (ml_get_combo_effect(ml, handled_bm, &effect))
- ml->play_effect(ml->dev, ml->private, &effect);
-
- ml_schedule_timer(ml);
-}
-
-static void ml_effect_timer(unsigned long timer_data)
-{
- struct input_dev *dev = (struct input_dev *)timer_data;
- struct ml_device *ml = dev->ff->private;
- unsigned long flags;
-
- pr_debug("timer: updating effects\n");
-
- spin_lock_irqsave(&dev->event_lock, flags);
- ml_play_effects(ml);
- spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
-/*
- * Sets requested gain for FF effects. Called with dev->event_lock held.
- */
-static void ml_ff_set_gain(struct input_dev *dev, u16 gain)
-{
- struct ml_device *ml = dev->ff->private;
- int i;
-
- ml->gain = gain;
-
- for (i = 0; i < FF_MEMLESS_EFFECTS; i++)
- __clear_bit(FF_EFFECT_PLAYING, &ml->states[i].flags);
-
- ml_play_effects(ml);
-}
-
-/*
- * Start/stop specified FF effect. Called with dev->event_lock held.
- */
-static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
-{
- struct ml_device *ml = dev->ff->private;
- struct ml_effect_state *state = &ml->states[effect_id];
-
- if (value > 0) {
- pr_debug("initiated play\n");
-
- __set_bit(FF_EFFECT_STARTED, &state->flags);
- state->count = value;
- state->play_at = jiffies +
- msecs_to_jiffies(state->effect->replay.delay);
- state->stop_at = state->play_at +
- msecs_to_jiffies(state->effect->replay.length);
- state->adj_at = state->play_at;
-
- } else {
- pr_debug("initiated stop\n");
-
- if (test_bit(FF_EFFECT_PLAYING, &state->flags))
- __set_bit(FF_EFFECT_ABORTING, &state->flags);
- else
- __clear_bit(FF_EFFECT_STARTED, &state->flags);
- }
-
- ml_play_effects(ml);
-
- return 0;
-}
-
-static int ml_ff_upload(struct input_dev *dev,
- struct ff_effect *effect, struct ff_effect *old)
-{
- struct ml_device *ml = dev->ff->private;
- struct ml_effect_state *state = &ml->states[effect->id];
-
- spin_lock_irq(&dev->event_lock);
-
- if (test_bit(FF_EFFECT_STARTED, &state->flags)) {
- __clear_bit(FF_EFFECT_PLAYING, &state->flags);
- state->play_at = jiffies +
- msecs_to_jiffies(state->effect->replay.delay);
- state->stop_at = state->play_at +
- msecs_to_jiffies(state->effect->replay.length);
- state->adj_at = state->play_at;
- ml_schedule_timer(ml);
- }
-
- spin_unlock_irq(&dev->event_lock);
-
- return 0;
-}
-
-static void ml_ff_destroy(struct ff_device *ff)
-{
- struct ml_device *ml = ff->private;
-
- kfree(ml->private);
-}
-
-/**
- * input_ff_create_memless() - create memoryless force-feedback device
- * @dev: input device supporting force-feedback
- * @data: driver-specific data to be passed into @play_effect
- * @play_effect: driver-specific method for playing FF effect
- */
-int input_ff_create_memless(struct input_dev *dev, void *data,
- int (*play_effect)(struct input_dev *, void *, struct ff_effect *))
-{
- struct ml_device *ml;
- struct ff_device *ff;
- int error;
- int i;
-
- ml = kzalloc(sizeof(struct ml_device), GFP_KERNEL);
- if (!ml)
- return -ENOMEM;
-
- ml->dev = dev;
- ml->private = data;
- ml->play_effect = play_effect;
- ml->gain = 0xffff;
- setup_timer(&ml->timer, ml_effect_timer, (unsigned long)dev);
-
- set_bit(FF_GAIN, dev->ffbit);
-
- error = input_ff_create(dev, FF_MEMLESS_EFFECTS);
- if (error) {
- kfree(ml);
- return error;
- }
-
- ff = dev->ff;
- ff->private = ml;
- ff->upload = ml_ff_upload;
- ff->playback = ml_ff_playback;
- ff->set_gain = ml_ff_set_gain;
- ff->destroy = ml_ff_destroy;
-
- /* we can emulate periodic effects with RUMBLE */
- if (test_bit(FF_RUMBLE, ff->ffbit)) {
- set_bit(FF_PERIODIC, dev->ffbit);
- set_bit(FF_SINE, dev->ffbit);
- set_bit(FF_TRIANGLE, dev->ffbit);
- set_bit(FF_SQUARE, dev->ffbit);
- }
-
- for (i = 0; i < FF_MEMLESS_EFFECTS; i++)
- ml->states[i].effect = &ff->effects[i];
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(input_ff_create_memless);
diff --git a/include/linux/input.h b/include/linux/input.h
index 82ce323..0c6c3f1 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -528,7 +528,4 @@ int input_ff_event(struct input_dev *dev, unsigned int type, unsigned int code,
int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, struct file *file);
int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
-int input_ff_create_memless(struct input_dev *dev, void *data,
- int (*play_effect)(struct input_dev *, void *, struct ff_effect *));
-
#endif
--
1.9.1
^ permalink raw reply related
* [PATCH 23/24] Port hid-lg4ff to ff-memless-next
From: Michal Malý @ 2014-04-09 11:35 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-lg4ff to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-lg4ff.c | 93 ++++++++++++++++++++++++++++++-------------------
2 files changed, 59 insertions(+), 36 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 8889b7a..5e6aa8e 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -390,7 +390,7 @@ config LOGIG940_FF
config LOGIWHEELS_FF
bool "Logitech wheels configuration and force feedback support"
depends on HID_LOGITECH
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
default LOGITECH_FF
help
Say Y here if you want to enable force feedback and range setting
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index 24883b4..d629093 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -25,6 +25,7 @@
#include <linux/input.h>
+#include <linux/input/ff-memless-next.h>
#include <linux/usb.h>
#include <linux/hid.h>
@@ -45,6 +46,8 @@
#define G27_REV_MIN 0x38
#define G27_2_REV_MIN 0x39
+#define FF_UPDATE_RATE 8
+
#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range);
@@ -69,6 +72,13 @@ struct lg4ff_device_entry {
static const signed short lg4ff_wheel_effects[] = {
FF_CONSTANT,
+ FF_RAMP,
+ FF_PERIODIC,
+ FF_SQUARE,
+ FF_TRIANGLE,
+ FF_SINE,
+ FF_SAW_UP,
+ FF_SAW_DOWN,
FF_AUTOCENTER,
-1
};
@@ -184,47 +194,60 @@ int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
}
}
-static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
+static int hid_lg4ff_start_combined(struct hid_device *hid, struct hid_report *report,
+ const struct mlnx_simple_force *force)
+{
+ __s32 *value = report->field[0]->value;
+ int scaled_x;
+
+ /* Scale down from MLNX range */
+ scaled_x = 0x80 - (force->x * 0xff / 0xffff);
+
+ value[0] = 0x11; /* Slot 1 */
+ value[1] = 0x08;
+ value[2] = scaled_x;
+ value[3] = 0x80;
+ value[4] = 0x00;
+ value[5] = 0x00;
+ value[6] = 0x00;
+
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+ return 0;
+}
+
+static int hid_lg4ff_stop_combined(struct hid_device *hid, struct hid_report *report)
+{
+ __s32 *value = report->field[0]->value;
+
+ value[0] = 0x13; /* Slot 1 */
+ value[1] = 0x00;
+ value[2] = 0x00;
+ value[3] = 0x00;
+ value[4] = 0x00;
+ value[5] = 0x00;
+ value[6] = 0x00;
+
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+ return 0;
+}
+
+static int hid_lg4ff_control(struct input_dev *dev, void *data, const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
- __s32 *value = report->field[0]->value;
- int x;
-
-#define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0)
-
- switch (effect->type) {
- case FF_CONSTANT:
- x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */
- CLAMP(x);
-
- if (x == 0x80) {
- /* De-activate force in slot-1*/
- value[0] = 0x13;
- value[1] = 0x00;
- value[2] = 0x00;
- value[3] = 0x00;
- value[4] = 0x00;
- value[5] = 0x00;
- value[6] = 0x00;
-
- hid_hw_request(hid, report, HID_REQ_SET_REPORT);
- return 0;
- }
-
- value[0] = 0x11; /* Slot 1 */
- value[1] = 0x08;
- value[2] = x;
- value[3] = 0x80;
- value[4] = 0x00;
- value[5] = 0x00;
- value[6] = 0x00;
- hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+ switch (command->cmd) {
+ case MLNX_START_COMBINED:
+ return hid_lg4ff_start_combined(hid, report, &command->u.simple_force);
+ break;
+ case MLNX_STOP_COMBINED:
+ return hid_lg4ff_stop_combined(hid, report);
break;
+ default:
+ dbg_hid("Unsupported effect command");
+ return -EINVAL;
}
- return 0;
}
/* Sends default autocentering command compatible with
@@ -610,7 +633,7 @@ int lg4ff_init(struct hid_device *hid)
for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++)
set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit);
- error = input_ff_create_memless(dev, NULL, hid_lg4ff_play);
+ error = input_ff_create_mlnx(dev, (void *)NULL, hid_lg4ff_control, FF_UPDATE_RATE);
if (error)
return error;
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 22/24] Port hid-lg2ff to ff-memless-next
From: Michal Malý @ 2014-04-09 11:33 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
- Port hid-lg2ff to ff-memless-next
- Clamp vibration magnitude to range <0x02; 0xfd> to prevent irregular shaking of the vibration motors.
Signed-off-by: Elias Vanderstuyft <elias.vds@gmail.com>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-lg2ff.c | 65 ++++++++++++++++++++++++++++++++++---------------
2 files changed, 47 insertions(+), 20 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 7d617a8..8889b7a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -372,7 +372,7 @@ config LOGITECH_FF
config LOGIRUMBLEPAD2_FF
bool "Logitech force feedback support (variant 2)"
depends on HID_LOGITECH
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
help
Say Y here if you want to enable force feedback support for:
- Logitech RumblePad
diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c
index 0e3fb1a..6ab5327 100644
--- a/drivers/hid/hid-lg2ff.c
+++ b/drivers/hid/hid-lg2ff.c
@@ -22,42 +22,69 @@
#include <linux/input.h>
+#include <linux/input/ff-memless-next.h>
#include <linux/slab.h>
#include <linux/hid.h>
#include "hid-lg.h"
+#define FF_UPDATE_RATE 8
+
struct lg2ff_device {
struct hid_report *report;
};
-static int play_effect(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+static int hid_lg2ff_start_rumble(struct hid_device *hid, struct hid_report *report,
+ const struct mlnx_rumble_force *rumble)
{
- struct hid_device *hid = input_get_drvdata(dev);
- struct lg2ff_device *lg2ff = data;
int weak, strong;
- strong = effect->u.rumble.strong_magnitude;
- weak = effect->u.rumble.weak_magnitude;
+#define CLAMP_QUIRK(x) do { if (x < 2) x = 2; else if (x > 0xfd) x = 0xfd; } \
+ while (0)
- if (weak || strong) {
- weak = weak * 0xff / 0xffff;
- strong = strong * 0xff / 0xffff;
+ /* Scale down from MLNX range */
+ strong = rumble->strong * 0xff / 0xffff;
+ weak = rumble->weak * 0xff / 0xffff;
+ CLAMP_QUIRK(weak);
+ CLAMP_QUIRK(strong);
- lg2ff->report->field[0]->value[0] = 0x51;
- lg2ff->report->field[0]->value[2] = weak;
- lg2ff->report->field[0]->value[4] = strong;
- } else {
- lg2ff->report->field[0]->value[0] = 0xf3;
- lg2ff->report->field[0]->value[2] = 0x00;
- lg2ff->report->field[0]->value[4] = 0x00;
- }
+ report->field[0]->value[0] = 0x51;
+ report->field[0]->value[2] = weak;
+ report->field[0]->value[4] = strong;
- hid_hw_request(hid, lg2ff->report, HID_REQ_SET_REPORT);
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
return 0;
}
+static int hid_lg2ff_stop_rumble(struct hid_device *hid, struct hid_report *report)
+{
+ report->field[0]->value[0] = 0xf3;
+ report->field[0]->value[2] = 0x00;
+ report->field[0]->value[4] = 0x00;
+
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+ return 0;
+}
+
+static int hid_lg2ff_control(struct input_dev *dev, void *data,
+ const struct mlnx_effect_command *command)
+{
+ struct hid_device *hid = input_get_drvdata(dev);
+ struct lg2ff_device *lg2ff = data;
+
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ return hid_lg2ff_start_rumble(hid, lg2ff->report, &command->u.rumble_force);
+ break;
+ case MLNX_STOP_RUMBLE:
+ return hid_lg2ff_stop_rumble(hid, lg2ff->report);
+ break;
+ default:
+ dbg_hid("Unsupported effect command");
+ return -EINVAL;
+ }
+}
+
int lg2ff_init(struct hid_device *hid)
{
struct lg2ff_device *lg2ff;
@@ -78,7 +105,7 @@ int lg2ff_init(struct hid_device *hid)
set_bit(FF_RUMBLE, dev->ffbit);
- error = input_ff_create_memless(dev, lg2ff, play_effect);
+ error = input_ff_create_mlnx(dev, lg2ff, hid_lg2ff_control, FF_UPDATE_RATE);
if (error) {
kfree(lg2ff);
return error;
--
1.9.1
^ permalink raw reply related
* [PATCH 21/24] Port xpad to ff-memless-next
From: Michal Malý @ 2014-04-09 11:31 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port xpad to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/input/joystick/Kconfig | 2 +-
drivers/input/joystick/xpad.c | 125 +++++++++++++++++++++++------------------
2 files changed, 71 insertions(+), 56 deletions(-)
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index 2dd3ba1..9f26e48 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -294,7 +294,7 @@ config JOYSTICK_XPAD
config JOYSTICK_XPAD_FF
bool "X-Box gamepad rumble support"
depends on JOYSTICK_XPAD && INPUT
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Say Y here if you want to take advantage of xbox 360 rumble features.
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 603fe0d..5d9c8a2 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -78,6 +78,7 @@
#include <linux/stat.h>
#include <linux/module.h>
#include <linux/usb/input.h>
+#include <linux/input/ff-memless-next.h>
#define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>"
#define DRIVER_DESC "X-Box pad driver"
@@ -97,6 +98,8 @@
#define XTYPE_XBOX360W 2
#define XTYPE_UNKNOWN 3
+#define FF_UPDATE_RATE 50
+
static bool dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
@@ -628,63 +631,75 @@ static void xpad_stop_output(struct usb_xpad *xpad) {}
#endif
#ifdef CONFIG_JOYSTICK_XPAD_FF
-static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
+static int xpad_play_effect(struct input_dev *dev, void *data,
+ const struct mlnx_effect_command *command)
{
struct usb_xpad *xpad = input_get_drvdata(dev);
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
+ __u16 strong, weak;
- if (effect->type == FF_RUMBLE) {
- __u16 strong = effect->u.rumble.strong_magnitude;
- __u16 weak = effect->u.rumble.weak_magnitude;
-
- switch (xpad->xtype) {
-
- case XTYPE_XBOX:
- xpad->odata[0] = 0x00;
- xpad->odata[1] = 0x06;
- xpad->odata[2] = 0x00;
- xpad->odata[3] = strong / 256; /* left actuator */
- xpad->odata[4] = 0x00;
- xpad->odata[5] = weak / 256; /* right actuator */
- xpad->irq_out->transfer_buffer_length = 6;
-
- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
-
- case XTYPE_XBOX360:
- xpad->odata[0] = 0x00;
- xpad->odata[1] = 0x08;
- xpad->odata[2] = 0x00;
- xpad->odata[3] = strong / 256; /* left actuator? */
- xpad->odata[4] = weak / 256; /* right actuator? */
- xpad->odata[5] = 0x00;
- xpad->odata[6] = 0x00;
- xpad->odata[7] = 0x00;
- xpad->irq_out->transfer_buffer_length = 8;
-
- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
-
- case XTYPE_XBOX360W:
- xpad->odata[0] = 0x00;
- xpad->odata[1] = 0x01;
- xpad->odata[2] = 0x0F;
- xpad->odata[3] = 0xC0;
- xpad->odata[4] = 0x00;
- xpad->odata[5] = strong / 256;
- xpad->odata[6] = weak / 256;
- xpad->odata[7] = 0x00;
- xpad->odata[8] = 0x00;
- xpad->odata[9] = 0x00;
- xpad->odata[10] = 0x00;
- xpad->odata[11] = 0x00;
- xpad->irq_out->transfer_buffer_length = 12;
-
- return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
-
- default:
- dev_dbg(&xpad->dev->dev,
- "%s - rumble command sent to unsupported xpad type: %d\n",
- __func__, xpad->xtype);
- return -1;
- }
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ strong = rumble_force->strong;
+ weak = rumble_force->weak;
+ break;
+ case MLNX_STOP_RUMBLE:
+ strong = 0;
+ weak = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+
+ switch (xpad->xtype) {
+
+ case XTYPE_XBOX:
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x06;
+ xpad->odata[2] = 0x00;
+ xpad->odata[3] = strong / 256; /* left actuator */
+ xpad->odata[4] = 0x00;
+ xpad->odata[5] = weak / 256; /* right actuator */
+ xpad->irq_out->transfer_buffer_length = 6;
+
+ return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+
+ case XTYPE_XBOX360:
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x08;
+ xpad->odata[2] = 0x00;
+ xpad->odata[3] = strong / 256; /* left actuator? */
+ xpad->odata[4] = weak / 256; /* right actuator? */
+ xpad->odata[5] = 0x00;
+ xpad->odata[6] = 0x00;
+ xpad->odata[7] = 0x00;
+ xpad->irq_out->transfer_buffer_length = 8;
+
+ return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+
+ case XTYPE_XBOX360W:
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x01;
+ xpad->odata[2] = 0x0F;
+ xpad->odata[3] = 0xC0;
+ xpad->odata[4] = 0x00;
+ xpad->odata[5] = strong / 256;
+ xpad->odata[6] = weak / 256;
+ xpad->odata[7] = 0x00;
+ xpad->odata[8] = 0x00;
+ xpad->odata[9] = 0x00;
+ xpad->odata[10] = 0x00;
+ xpad->odata[11] = 0x00;
+ xpad->irq_out->transfer_buffer_length = 12;
+
+ return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+
+ default:
+ dev_dbg(&xpad->dev->dev,
+ "%s - rumble command sent to unsupported xpad type: %d\n",
+ __func__, xpad->xtype);
+ return -1;
}
return 0;
@@ -697,7 +712,7 @@ static int xpad_init_ff(struct usb_xpad *xpad)
input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
- return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
+ return input_ff_create_mlnx(xpad->dev, NULL, xpad_play_effect, FF_UPDATE_RATE);
}
#else
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 20/24] Port gamecon to ff-memless-next
From: Michal Malý @ 2014-04-09 11:30 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port gamecon to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/input/joystick/Kconfig | 2 +-
drivers/input/joystick/gamecon.c | 57 ++++++++++++++++++++++------------------
2 files changed, 33 insertions(+), 26 deletions(-)
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index 56eb471..2dd3ba1 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -221,7 +221,7 @@ config JOYSTICK_DB9
config JOYSTICK_GAMECON
tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads"
depends on PARPORT
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Say Y here if you have a Nintendo Entertainment System gamepad,
Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad,
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index e68e497..209d0fb 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -40,6 +40,7 @@
#include <linux/input.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/input/ff-memless-next.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
@@ -47,6 +48,7 @@ MODULE_LICENSE("GPL");
#define GC_MAX_PORTS 3
#define GC_MAX_DEVICES 5
+#define FF_UPDATE_RATE 50
struct gc_config {
int args[GC_MAX_DEVICES + 1];
@@ -263,43 +265,48 @@ static void gc_n64_process_packet(struct gc *gc)
}
static int gc_n64_play_effect(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+ const struct mlnx_effect_command *command)
{
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
int i;
unsigned long flags;
struct gc *gc = input_get_drvdata(dev);
struct gc_subdev *sdev = data;
unsigned char target = 1 << sdev->idx; /* select desired pin */
+ unsigned int cmd;
- if (effect->type == FF_RUMBLE) {
- struct ff_rumble_effect *rumble = &effect->u.rumble;
- unsigned int cmd =
- rumble->strong_magnitude || rumble->weak_magnitude ?
- GC_N64_CMD_01 : GC_N64_CMD_00;
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ cmd = (rumble_force->strong || rumble_force->weak) ? GC_N64_CMD_01 : GC_N64_CMD_00;
+ break;
+ case MLNX_STOP_RUMBLE:
+ cmd = GC_N64_CMD_00;
+ break;
+ default:
+ return -EINVAL;
+ }
- local_irq_save(flags);
+ local_irq_save(flags);
- /* Init Rumble - 0x03, 0x80, 0x01, (34)0x80 */
- gc_n64_send_command(gc, GC_N64_CMD_03, target);
+ /* Init Rumble - 0x03, 0x80, 0x01, (34)0x80 */
+ gc_n64_send_command(gc, GC_N64_CMD_03, target);
+ gc_n64_send_command(gc, GC_N64_CMD_80, target);
+ gc_n64_send_command(gc, GC_N64_CMD_01, target);
+ for (i = 0; i < 32; i++)
gc_n64_send_command(gc, GC_N64_CMD_80, target);
- gc_n64_send_command(gc, GC_N64_CMD_01, target);
- for (i = 0; i < 32; i++)
- gc_n64_send_command(gc, GC_N64_CMD_80, target);
- gc_n64_send_stop_bit(gc, target);
+ gc_n64_send_stop_bit(gc, target);
- udelay(GC_N64_DELAY);
-
- /* Now start or stop it - 0x03, 0xc0, 0zx1b, (32)0x01/0x00 */
- gc_n64_send_command(gc, GC_N64_CMD_03, target);
- gc_n64_send_command(gc, GC_N64_CMD_c0, target);
- gc_n64_send_command(gc, GC_N64_CMD_1b, target);
- for (i = 0; i < 32; i++)
- gc_n64_send_command(gc, cmd, target);
- gc_n64_send_stop_bit(gc, target);
+ udelay(GC_N64_DELAY);
- local_irq_restore(flags);
+ /* Now start or stop it - 0x03, 0xc0, 0zx1b, (32)0x01/0x00 */
+ gc_n64_send_command(gc, GC_N64_CMD_03, target);
+ gc_n64_send_command(gc, GC_N64_CMD_c0, target);
+ gc_n64_send_command(gc, GC_N64_CMD_1b, target);
+ for (i = 0; i < 32; i++)
+ gc_n64_send_command(gc, cmd, target);
+ gc_n64_send_stop_bit(gc, target);
- }
+ local_irq_restore(flags);
return 0;
}
@@ -317,7 +324,7 @@ static int __init gc_n64_init_ff(struct input_dev *dev, int i)
input_set_capability(dev, EV_FF, FF_RUMBLE);
- err = input_ff_create_memless(dev, sdev, gc_n64_play_effect);
+ err = input_ff_create_mlnx(dev, sdev, gc_n64_play_effect, FF_UPDATE_RATE);
if (err) {
kfree(sdev);
return err;
--
1.9.1
^ permalink raw reply related
* [PATCH 19/24] Port hid-zpff to ff-memless-next
From: Michal Malý @ 2014-04-09 11:29 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-zpff to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-zpff.c | 30 ++++++++++++++++++++++--------
2 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index d1cbad6..7d617a8 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -775,7 +775,7 @@ config HID_ZEROPLUS
config ZEROPLUS_FF
bool "Zeroplus based game controller force feedback support"
depends on HID_ZEROPLUS
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Say Y here if you have a Zeroplus based game controller and want
to have force feedback support for it.
diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c
index a29756c..6912500 100644
--- a/drivers/hid/hid-zpff.c
+++ b/drivers/hid/hid-zpff.c
@@ -25,9 +25,12 @@
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-ids.h"
+#define FF_UPDATE_RATE 50
+
#ifdef CONFIG_ZEROPLUS_FF
struct zpff_device {
@@ -35,10 +38,11 @@ struct zpff_device {
};
static int zpff_play(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+ const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct zpff_device *zpff = data;
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
int left, right;
/*
@@ -47,12 +51,22 @@ static int zpff_play(struct input_dev *dev, void *data,
* however it is possible that the XFX Executioner is an exception
*/
- left = effect->u.rumble.strong_magnitude;
- right = effect->u.rumble.weak_magnitude;
- dbg_hid("called with 0x%04x 0x%04x\n", left, right);
-
- left = left * 0x7f / 0xffff;
- right = right * 0x7f / 0xffff;
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ left = rumble_force->strong;
+ right = rumble_force->weak;
+ dbg_hid("called with 0x%04x 0x%04x\n", left, right);
+
+ left = left * 0x7f / 0xffff;
+ right = right * 0x7f / 0xffff;
+ break;
+ case MLNX_STOP_RUMBLE:
+ left = 0;
+ right = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
zpff->report->field[2]->value[0] = left;
zpff->report->field[3]->value[0] = right;
@@ -83,7 +97,7 @@ static int zpff_init(struct hid_device *hid)
set_bit(FF_RUMBLE, dev->ffbit);
- error = input_ff_create_memless(dev, zpff, zpff_play);
+ error = input_ff_create_mlnx(dev, zpff, zpff_play, FF_UPDATE_RATE);
if (error) {
kfree(zpff);
return error;
--
1.9.1
^ permalink raw reply related
* [PATCH 18/24] Port hid-wiimote-modules to ff-memless-next
From: Michal Malý @ 2014-04-09 11:28 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-wiimote-modules to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-wiimote-modules.c | 74 ++++++++++++++++++++++++---------------
2 files changed, 46 insertions(+), 30 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index ee999bc..d1cbad6 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -738,7 +738,7 @@ config HID_WIIMOTE
depends on HID
depends on LEDS_CLASS
select POWER_SUPPLY
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Support for Nintendo Wii and Wii U Bluetooth peripherals. Supported
devices are the Wii Remote and its extension devices, but also devices
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 6b61f01..95b20ea 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -37,8 +37,11 @@
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/spinlock.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-wiimote.h"
+#define FF_UPDATE_RATE 50
+
/*
* Keys
* The initial Wii Remote provided a bunch of buttons that are reported as
@@ -131,21 +134,27 @@ static void wiimod_rumble_worker(struct work_struct *work)
}
static int wiimod_rumble_play(struct input_dev *dev, void *data,
- struct ff_effect *eff)
+ const struct mlnx_effect_command *command)
{
struct wiimote_data *wdata = input_get_drvdata(dev);
- __u8 value;
-
- /*
- * The wiimote supports only a single rumble motor so if any magnitude
- * is set to non-zero then we start the rumble motor. If both are set to
- * zero, we stop the rumble motor.
- */
-
- if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude)
- value = 1;
- else
- value = 0;
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
+ __u8 value = 0;
+
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ /*
+ * The wiimote supports only a single rumble motor so if any magnitude
+ * is set to non-zero then we start the rumble motor. If both are set to
+ * zero, we stop the rumble motor.
+ */
+ if (rumble_force->strong || rumble_force->weak)
+ value = 1;
+ break;
+ case MLNX_STOP_RUMBLE:
+ break;
+ default:
+ return -EINVAL;
+ }
/* Locking state.lock here might deadlock with input_event() calls.
* schedule_work acts as barrier. Merging multiple changes is fine. */
@@ -161,7 +170,7 @@ static int wiimod_rumble_probe(const struct wiimod_ops *ops,
INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker);
set_bit(FF_RUMBLE, wdata->input->ffbit);
- if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play))
+ if (input_ff_create_mlnx(wdata->input, NULL, wiimod_rumble_play, FF_UPDATE_RATE))
return -ENOMEM;
return 0;
@@ -1771,21 +1780,28 @@ static void wiimod_pro_close(struct input_dev *dev)
}
static int wiimod_pro_play(struct input_dev *dev, void *data,
- struct ff_effect *eff)
+ const struct mlnx_effect_command *command)
{
struct wiimote_data *wdata = input_get_drvdata(dev);
- __u8 value;
-
- /*
- * The wiimote supports only a single rumble motor so if any magnitude
- * is set to non-zero then we start the rumble motor. If both are set to
- * zero, we stop the rumble motor.
- */
-
- if (eff->u.rumble.strong_magnitude || eff->u.rumble.weak_magnitude)
- value = 1;
- else
- value = 0;
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
+ __u8 value = 0;
+
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ /*
+ * The wiimote supports only a single rumble motor so if any magnitude
+ * is set to non-zero then we start the rumble motor. If both are set to
+ * zero, we stop the rumble motor.
+ */
+
+ if (rumble_force->strong || rumble_force->weak)
+ value = 1;
+ break;
+ case MLNX_STOP_RUMBLE:
+ break;
+ default:
+ return -EINVAL;
+ }
/* Locking state.lock here might deadlock with input_event() calls.
* schedule_work acts as barrier. Merging multiple changes is fine. */
@@ -1867,8 +1883,8 @@ static int wiimod_pro_probe(const struct wiimod_ops *ops,
set_bit(FF_RUMBLE, wdata->extension.input->ffbit);
input_set_drvdata(wdata->extension.input, wdata);
- if (input_ff_create_memless(wdata->extension.input, NULL,
- wiimod_pro_play)) {
+ if (input_ff_create_mlnx(wdata->extension.input, NULL,
+ wiimod_pro_play, FF_UPDATE_RATE)) {
ret = -ENOMEM;
goto err_free;
}
--
1.9.1
^ permalink raw reply related
* [PATCH 17/24] Port hid-tmff to ff-memless-next
From: Michal Malý @ 2014-04-09 11:28 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-tmff to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-tmff.c | 83 ++++++++++++++++++++++++++++++--------------------
2 files changed, 51 insertions(+), 34 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index fc22f72..ee999bc 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -719,7 +719,7 @@ config HID_THRUSTMASTER
config THRUSTMASTER_FF
bool "ThrustMaster devices force feedback support"
depends on HID_THRUSTMASTER
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or 3,
a THRUSTMASTER Dual Trigger 3-in-1 or a THRUSTMASTER Ferrari GT
diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c
index b833760..3df000c 100644
--- a/drivers/hid/hid-tmff.c
+++ b/drivers/hid/hid-tmff.c
@@ -31,9 +31,12 @@
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-ids.h"
+#define FF_UPDATE_RATE 50
+
static const signed short ff_rumble[] = {
FF_RUMBLE,
-1
@@ -41,6 +44,13 @@ static const signed short ff_rumble[] = {
static const signed short ff_joystick[] = {
FF_CONSTANT,
+ FF_RAMP,
+ FF_PERIODIC,
+ FF_SINE,
+ FF_SQUARE,
+ FF_TRIANGLE,
+ FF_SAW_DOWN,
+ FF_SAW_UP,
-1
};
@@ -67,12 +77,12 @@ static inline int tmff_scale_u16(unsigned int in, int minimum, int maximum)
return ret;
}
-/* Changes values from -0x80 to 0x7f into values from minimum to maximum */
-static inline int tmff_scale_s8(int in, int minimum, int maximum)
+/* Changes values from -0x7fff to 0x7fff into values from minimum to maximum */
+static inline int tmff_scale_s32(int in, int minimum, int maximum)
{
int ret;
- ret = (((in + 0x80) * (maximum - minimum)) / 0xff) + minimum;
+ ret = (((in + 0x7fff) * (maximum - minimum)) / 0xffff) + minimum;
if (ret < minimum)
return minimum;
if (ret > maximum)
@@ -81,43 +91,50 @@ static inline int tmff_scale_s8(int in, int minimum, int maximum)
}
static int tmff_play(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+ const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct tmff_device *tmff = data;
struct hid_field *ff_field = tmff->ff_field;
int x, y;
- int left, right; /* Rumbling */
-
- switch (effect->type) {
- case FF_CONSTANT:
- x = tmff_scale_s8(effect->u.ramp.start_level,
- ff_field->logical_minimum,
- ff_field->logical_maximum);
- y = tmff_scale_s8(effect->u.ramp.end_level,
- ff_field->logical_minimum,
- ff_field->logical_maximum);
-
- dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
- ff_field->value[0] = x;
- ff_field->value[1] = y;
- hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
- break;
- case FF_RUMBLE:
- left = tmff_scale_u16(effect->u.rumble.weak_magnitude,
- ff_field->logical_minimum,
- ff_field->logical_maximum);
- right = tmff_scale_u16(effect->u.rumble.strong_magnitude,
- ff_field->logical_minimum,
- ff_field->logical_maximum);
-
- dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
- ff_field->value[0] = left;
- ff_field->value[1] = right;
- hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
+ switch (command->cmd) {
+ case MLNX_START_COMBINED: {
+ const struct mlnx_simple_force *sf = &command->u.simple_force;
+ x = tmff_scale_s32(sf->x,
+ ff_field->logical_minimum,
+ ff_field->logical_maximum);
+ y = tmff_scale_s32(sf->y,
+ ff_field->logical_minimum,
+ ff_field->logical_maximum);
+ break;
+ }
+ case MLNX_STOP_COMBINED:
+ x = 0;
+ y = 0;
+ break;
+ case MLNX_START_RUMBLE: {
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
+ x = tmff_scale_u16(rumble_force->weak,
+ ff_field->logical_minimum,
+ ff_field->logical_maximum);
+ y = tmff_scale_u16(rumble_force->strong,
+ ff_field->logical_minimum,
+ ff_field->logical_maximum);
break;
+ }
+ case MLNX_STOP_RUMBLE:
+ x = 0;
+ y = 0;
+ break;
+ default:
+ return -EINVAL;
}
+
+ ff_field->value[0] = x;
+ ff_field->value[1] = y;
+
+ hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
return 0;
}
@@ -192,7 +209,7 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
goto fail;
}
- error = input_ff_create_memless(input_dev, tmff, tmff_play);
+ error = input_ff_create_mlnx(input_dev, tmff, tmff_play, FF_UPDATE_RATE);
if (error)
goto fail;
--
1.9.1
^ permalink raw reply related
* [PATCH 16/24] Port hid-sony to ff-memless-next
From: Michal Malý @ 2014-04-09 11:27 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-sony to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-sony.c | 24 ++++++++++++++++++------
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index e76c36a..fc22f72 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -623,7 +623,7 @@ config HID_SONY
config SONY_FF
bool "Sony PS2/3 accessories force feedback support"
depends on HID_SONY
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Say Y here if you have a Sony PS2/3 accessory and want to enable force
feedback support for it.
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 2f19b15..70a9cc5 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -30,6 +30,7 @@
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/leds.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-ids.h"
@@ -44,6 +45,7 @@
#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER | DUALSHOCK4_CONTROLLER_USB)
#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER_USB | DUALSHOCK4_CONTROLLER_USB)
+#define FF_UPDATE_RATE 50
#define MAX_LEDS 4
static const u8 sixaxis_rdesc_fixup[] = {
@@ -970,16 +972,25 @@ static void dualshock4_state_worker(struct work_struct *work)
#ifdef CONFIG_SONY_FF
static int sony_play_effect(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+ const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct sony_sc *sc = hid_get_drvdata(hid);
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
- if (effect->type != FF_RUMBLE)
- return 0;
- sc->left = effect->u.rumble.strong_magnitude / 256;
- sc->right = effect->u.rumble.weak_magnitude / 256;
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ sc->left = rumble_force->strong / 256;
+ sc->right = rumble_force->weak / 256;
+ break;
+ case MLNX_STOP_RUMBLE:
+ sc->left = 0;
+ sc->right = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
schedule_work(&sc->state_worker);
return 0;
@@ -992,7 +1003,7 @@ static int sony_init_ff(struct hid_device *hdev)
struct input_dev *input_dev = hidinput->input;
input_set_capability(input_dev, EV_FF, FF_RUMBLE);
- return input_ff_create_memless(input_dev, NULL, sony_play_effect);
+ return input_ff_create_mlnx(input_dev, NULL, sony_play_effect, FF_UPDATE_RATE);
}
#else
@@ -1150,6 +1161,7 @@ static const struct hid_device_id sony_devices[] = {
.driver_data = DUALSHOCK4_CONTROLLER_USB },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
.driver_data = DUALSHOCK4_CONTROLLER_BT },
+
{ }
};
MODULE_DEVICE_TABLE(hid, sony_devices);
--
1.9.1
^ permalink raw reply related
* [PATCH 15/24] Port hid-sjoy to ff-memless-next
From: Michal Malý @ 2014-04-09 11:26 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-sjoy to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-sjoy.c | 35 +++++++++++++++++++++++++----------
2 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 87a02cc..e76c36a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -681,7 +681,7 @@ config HID_SMARTJOYPLUS
config SMARTJOYPLUS_FF
bool "SmartJoy PLUS PS2/USB adapter force feedback support"
depends on HID_SMARTJOYPLUS
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Say Y here if you have a SmartJoy PLUS PS2/USB adapter and want to
enable force feedback support for it.
diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c
index 37845ec..a6f8cfe 100644
--- a/drivers/hid/hid-sjoy.c
+++ b/drivers/hid/hid-sjoy.c
@@ -30,8 +30,11 @@
#include <linux/slab.h>
#include <linux/hid.h>
#include <linux/module.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-ids.h"
+#define FF_UPDATE_RATE 50
+
#ifdef CONFIG_SMARTJOYPLUS_FF
struct sjoyff_device {
@@ -39,21 +42,33 @@ struct sjoyff_device {
};
static int hid_sjoyff_play(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+ const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct sjoyff_device *sjoyff = data;
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
u32 left, right;
- left = effect->u.rumble.strong_magnitude;
- right = effect->u.rumble.weak_magnitude;
- dev_dbg(&dev->dev, "called with 0x%08x 0x%08x\n", left, right);
-
- left = left * 0xff / 0xffff;
- right = (right != 0); /* on/off only */
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ left = rumble_force->strong;
+ right = rumble_force->weak;
+ dev_dbg(&dev->dev, "called with 0x%08x 0x%08x\n", left, right);
+
+ left = left * 0xff / 0xffff;
+ right = (right != 0); /* on/off only */
+
+ sjoyff->report->field[0]->value[1] = right;
+ sjoyff->report->field[0]->value[2] = left;
+ break;
+ case MLNX_STOP_RUMBLE:
+ left = 0;
+ right = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
- sjoyff->report->field[0]->value[1] = right;
- sjoyff->report->field[0]->value[2] = left;
dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right);
hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT);
@@ -103,7 +118,7 @@ static int sjoyff_init(struct hid_device *hid)
set_bit(FF_RUMBLE, dev->ffbit);
- error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
+ error = input_ff_create_mlnx(dev, sjoyff, hid_sjoyff_play, FF_UPDATE_RATE);
if (error) {
kfree(sjoyff);
return error;
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 14/24] Port hid-pl to ff-memless-next
From: Michal Malý @ 2014-04-09 11:25 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-pl to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-pl.c | 38 ++++++++++++++++++++++++++------------
2 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 6f2941a..87a02cc 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -500,7 +500,7 @@ config HID_PANTHERLORD
config PANTHERLORD_FF
bool "Pantherlord force feedback support"
depends on HID_PANTHERLORD
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Say Y here if you have a PantherLord/GreenAsia based game controller
or adapter and want to enable force feedback support for it.
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c
index 2dcd7d9..9b539d5 100644
--- a/drivers/hid/hid-pl.c
+++ b/drivers/hid/hid-pl.c
@@ -44,9 +44,12 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/hid.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-ids.h"
+#define FF_UPDATE_RATE 50
+
#ifdef CONFIG_PANTHERLORD_FF
struct plff_device {
@@ -57,24 +60,35 @@ struct plff_device {
};
static int hid_plff_play(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+ const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct plff_device *plff = data;
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
int left, right;
- left = effect->u.rumble.strong_magnitude;
- right = effect->u.rumble.weak_magnitude;
- debug("called with 0x%04x 0x%04x", left, right);
-
- left = left * plff->maxval / 0xffff;
- right = right * plff->maxval / 0xffff;
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ left = rumble_force->strong;
+ right = rumble_force->weak;
+ debug("called with 0x%04x 0x%04x", left, right);
+
+ left = left * plff->maxval / 0xffff;
+ right = right * plff->maxval / 0xffff;
+
+ *plff->strong = left;
+ *plff->weak = right;
+ debug("running with 0x%02x 0x%02x", left, right);
+ break;
+ case MLNX_STOP_RUMBLE:
+ *plff->strong = 0;
+ *plff->weak = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
- *plff->strong = left;
- *plff->weak = right;
- debug("running with 0x%02x 0x%02x", left, right);
hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT);
-
return 0;
}
@@ -160,7 +174,7 @@ static int plff_init(struct hid_device *hid)
set_bit(FF_RUMBLE, dev->ffbit);
- error = input_ff_create_memless(dev, plff, hid_plff_play);
+ error = input_ff_create_mlnx(dev, plff, hid_plff_play, FF_UPDATE_RATE);
if (error) {
kfree(plff);
return error;
--
1.9.1
^ permalink raw reply related
* [PATCH 13/24] Port hid-lg3ff to ff-memless-next
From: Michal Malý @ 2014-04-09 11:24 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-lg3ff to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-lg3ff.c | 56 +++++++++++++++++++++++++++++++------------------
2 files changed, 37 insertions(+), 21 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index c7794ae..6f2941a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -382,7 +382,7 @@ config LOGIRUMBLEPAD2_FF
config LOGIG940_FF
bool "Logitech Flight System G940 force feedback support"
depends on HID_LOGITECH
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
help
Say Y here if you want to enable force feedback support for Logitech
Flight System G940 devices.
diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c
index 8c2da18..a85f8e5 100644
--- a/drivers/hid/hid-lg3ff.c
+++ b/drivers/hid/hid-lg3ff.c
@@ -23,9 +23,12 @@
#include <linux/input.h>
#include <linux/hid.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-lg.h"
+#define FF_UPDATE_RATE 50
+
/*
* G940 Theory of Operation (from experimentation)
*
@@ -58,12 +61,11 @@ struct lg3ff_device {
};
static int hid_lg3ff_play(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+ const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
- int x, y;
/*
* Available values in the field should always be 63, but we only use up to
@@ -72,30 +74,37 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data,
memset(report->field[0]->value, 0,
sizeof(__s32) * report->field[0]->report_count);
- switch (effect->type) {
- case FF_CONSTANT:
-/*
- * Already clamped in ff_memless
- * 0 is center (different then other logitech)
- */
- x = effect->u.ramp.start_level;
- y = effect->u.ramp.end_level;
-
- /* send command byte */
- report->field[0]->value[0] = 0x51;
+ /* send command byte */
+ report->field[0]->value[0] = 0x51;
-/*
- * Sign backwards from other Force3d pro
- * which get recast here in two's complement 8 bits
- */
+ switch (command->cmd) {
+ case MLNX_START_COMBINED: {
+ const struct mlnx_simple_force *simple_force = &command->u.simple_force;
+ /* Scale down from MLNX range */
+ const int x = 0x80 - (simple_force->x * 0xff / 0xffff);
+ const int y = simple_force->y * 0xff / 0xffff;
+
+ /*
+ * Sign backwards from other Force3d pro
+ * which get recast here in two's complement 8 bits
+ */
report->field[0]->value[1] = (unsigned char)(-x);
report->field[0]->value[31] = (unsigned char)(-y);
-
- hid_hw_request(hid, report, HID_REQ_SET_REPORT);
break;
+ }
+ case MLNX_STOP_COMBINED:
+ report->field[0]->value[1] = 0;
+ report->field[0]->value[31] = 0;
+ break;
+ default:
+ return -EINVAL;
}
+
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+
return 0;
}
+
static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude)
{
struct hid_device *hid = input_get_drvdata(dev);
@@ -123,6 +132,13 @@ static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude)
static const signed short ff3_joystick_ac[] = {
FF_CONSTANT,
+ FF_RAMP,
+ FF_PERIODIC,
+ FF_SQUARE,
+ FF_TRIANGLE,
+ FF_SINE,
+ FF_SAW_UP,
+ FF_SAW_DOWN,
FF_AUTOCENTER,
-1
};
@@ -143,7 +159,7 @@ int lg3ff_init(struct hid_device *hid)
for (i = 0; ff_bits[i] >= 0; i++)
set_bit(ff_bits[i], dev->ffbit);
- error = input_ff_create_memless(dev, NULL, hid_lg3ff_play);
+ error = input_ff_create_mlnx(dev, NULL, hid_lg3ff_play, FF_UPDATE_RATE);
if (error)
return error;
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 12/24] Port hid-lgff to ff-memless-next
From: Michal Malý @ 2014-04-09 11:24 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-lgff to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-lgff.c | 63 ++++++++++++++++++++++++++++++++++----------------
2 files changed, 44 insertions(+), 21 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index d1d4e77..c7794ae 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -356,7 +356,7 @@ config HID_LOGITECH_DJ
config LOGITECH_FF
bool "Logitech force feedback support"
depends on HID_LOGITECH
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
help
Say Y here if you have one of these devices:
- Logitech WingMan Cordless RumblePad
diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c
index e1394af..b929a3a 100644
--- a/drivers/hid/hid-lgff.c
+++ b/drivers/hid/hid-lgff.c
@@ -31,9 +31,12 @@
#include <linux/input.h>
#include <linux/hid.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-lg.h"
+#define FF_UPDATE_RATE 50
+
struct dev_type {
u16 idVendor;
u16 idProduct;
@@ -47,6 +50,13 @@ static const signed short ff_rumble[] = {
static const signed short ff_joystick[] = {
FF_CONSTANT,
+ FF_RAMP,
+ FF_PERIODIC,
+ FF_SQUARE,
+ FF_TRIANGLE,
+ FF_SINE,
+ FF_SAW_UP,
+ FF_SAW_DOWN,
-1
};
@@ -66,45 +76,58 @@ static const struct dev_type devices[] = {
{ 0x046d, 0xc295, ff_joystick },
};
-static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
+static int hid_lgff_play(struct input_dev *dev, void *data,
+ const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
- int x, y;
- unsigned int left, right;
-#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff
+ switch (command->cmd) {
+ case MLNX_START_COMBINED: {
+ const struct mlnx_simple_force *simple_force = &command->u.simple_force;
+ /* Scale down from MLNX range */
+ const int x = 0x80 - (simple_force->x * 0xff / 0xffff);
+ const int y = simple_force->y * 0xff / 0xffff;
- switch (effect->type) {
- case FF_CONSTANT:
- x = effect->u.ramp.start_level + 0x7f; /* 0x7f is center */
- y = effect->u.ramp.end_level + 0x7f;
- CLAMP(x);
- CLAMP(y);
report->field[0]->value[0] = 0x51;
report->field[0]->value[1] = 0x08;
report->field[0]->value[2] = x;
report->field[0]->value[3] = y;
dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
- hid_hw_request(hid, report, HID_REQ_SET_REPORT);
break;
+ }
+ case MLNX_STOP_COMBINED:
+ report->field[0]->value[0] = 0x51;
+ report->field[0]->value[1] = 0x08;
+ report->field[0]->value[2] = 0;
+ report->field[0]->value[3] = 0;
+ break;
+ case MLNX_START_RUMBLE: {
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
+ /* Scale down from MLNX range */
+ const unsigned int right = rumble_force->weak * 0xff / 0xffff;
+ const unsigned int left = rumble_force->strong * 0xff / 0xffff;
- case FF_RUMBLE:
- right = effect->u.rumble.strong_magnitude;
- left = effect->u.rumble.weak_magnitude;
- right = right * 0xff / 0xffff;
- left = left * 0xff / 0xffff;
- CLAMP(left);
- CLAMP(right);
report->field[0]->value[0] = 0x42;
report->field[0]->value[1] = 0x00;
report->field[0]->value[2] = left;
report->field[0]->value[3] = right;
dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
- hid_hw_request(hid, report, HID_REQ_SET_REPORT);
break;
}
+ case MLNX_STOP_RUMBLE:
+ report->field[0]->value[0] = 0x42;
+ report->field[0]->value[1] = 0x00;
+ report->field[0]->value[2] = 0;
+ report->field[0]->value[3] = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+
return 0;
}
@@ -148,7 +171,7 @@ int lgff_init(struct hid_device* hid)
for (i = 0; ff_bits[i] >= 0; i++)
set_bit(ff_bits[i], dev->ffbit);
- error = input_ff_create_memless(dev, NULL, hid_lgff_play);
+ error = input_ff_create_mlnx(dev, NULL, hid_lgff_play, FF_UPDATE_RATE);
if (error)
return error;
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 11/24] Port hid-holtekff to ff-memless-next
From: Michal Malý @ 2014-04-09 11:23 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-holtekff to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-holtekff.c | 47 +++++++++++++++++++++++++++++-----------------
2 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 24b336e..d1d4e77 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -247,7 +247,7 @@ config HID_HOLTEK
config HOLTEK_FF
bool "Holtek On Line Grip force feedback support"
depends on HID_HOLTEK
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Say Y here if you have a Holtek On Line Grip based game controller
and want to have force feedback support for it.
diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c
index 9325545..9c6064d 100644
--- a/drivers/hid/hid-holtekff.c
+++ b/drivers/hid/hid-holtekff.c
@@ -27,9 +27,12 @@
#include <linux/input.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-ids.h"
+#define FF_UPDATE_RATE 50
+
#ifdef CONFIG_HOLTEK_FF
MODULE_LICENSE("GPL");
@@ -104,34 +107,44 @@ static void holtekff_send(struct holtekff_device *holtekff,
}
static int holtekff_play(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+ const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct holtekff_device *holtekff = data;
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
int left, right;
/* effect type 1, length 65535 msec */
u8 buf[HOLTEKFF_MSG_LENGTH] =
{ 0x01, 0x01, 0xff, 0xff, 0x10, 0xe0, 0x00 };
- left = effect->u.rumble.strong_magnitude;
- right = effect->u.rumble.weak_magnitude;
- dbg_hid("called with 0x%04x 0x%04x\n", left, right);
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ left = rumble_force->strong;
+ right = rumble_force->weak;
+ dbg_hid("called with 0x%04x 0x%04x\n", left, right);
- if (!left && !right) {
- holtekff_send(holtekff, hid, stop_all6);
- return 0;
- }
+ if (!left && !right) {
+ holtekff_send(holtekff, hid, stop_all6);
+ return 0;
+ }
- if (left)
- buf[1] |= 0x80;
- if (right)
- buf[1] |= 0x40;
+ if (left)
+ buf[1] |= 0x80;
+ if (right)
+ buf[1] |= 0x40;
- /* The device takes a single magnitude, so we just sum them up. */
- buf[6] = min(0xf, (left >> 12) + (right >> 12));
+ /* The device takes a single magnitude, so we just sum them up. */
+ buf[6] = min(0xf, (left >> 12) + (right >> 12));
- holtekff_send(holtekff, hid, buf);
- holtekff_send(holtekff, hid, start_effect_1);
+ holtekff_send(holtekff, hid, buf);
+ holtekff_send(holtekff, hid, start_effect_1);
+ return 0;
+ case MLNX_STOP_RUMBLE:
+ holtekff_send(holtekff, hid, stop_all6);
+ return 0;
+ default:
+ return -EINVAL;
+ }
return 0;
}
@@ -171,7 +184,7 @@ static int holtekff_init(struct hid_device *hid)
holtekff_send(holtekff, hid, stop_all4);
holtekff_send(holtekff, hid, stop_all6);
- error = input_ff_create_memless(dev, holtekff, holtekff_play);
+ error = input_ff_create_mlnx(dev, holtekff, holtekff_play, FF_UPDATE_RATE);
if (error) {
kfree(holtekff);
return error;
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 10/24] Port hid-gaff to ff-memless-next
From: Michal Malý @ 2014-04-09 11:22 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-gaff to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-gaff.c | 32 +++++++++++++++++++++++---------
2 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 0ba1962..24b336e 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -656,7 +656,7 @@ config HID_GREENASIA
config GREENASIA_FF
bool "GreenAsia (Product ID 0x12) force feedback support"
depends on HID_GREENASIA
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
(like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c
index 2d8cead..f2f70c1 100644
--- a/drivers/hid/hid-gaff.c
+++ b/drivers/hid/hid-gaff.c
@@ -31,8 +31,11 @@
#include <linux/slab.h>
#include <linux/hid.h>
#include <linux/module.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-ids.h"
+#define FF_UPDATE_RATE 50
+
#ifdef CONFIG_GREENASIA_FF
struct gaff_device {
@@ -40,19 +43,30 @@ struct gaff_device {
};
static int hid_gaff_play(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+ const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct gaff_device *gaff = data;
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
int left, right;
- left = effect->u.rumble.strong_magnitude;
- right = effect->u.rumble.weak_magnitude;
-
- dbg_hid("called with 0x%04x 0x%04x", left, right);
-
- left = left * 0xfe / 0xffff;
- right = right * 0xfe / 0xffff;
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ left = rumble_force->strong;
+ right = rumble_force->weak;
+
+ dbg_hid("called with 0x%04x 0x%04x", left, right);
+
+ left = left * 0xfe / 0xffff;
+ right = right * 0xfe / 0xffff;
+ break;
+ case MLNX_STOP_RUMBLE:
+ left = 0;
+ right = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
gaff->report->field[0]->value[0] = 0x51;
gaff->report->field[0]->value[1] = 0x0;
@@ -109,7 +123,7 @@ static int gaff_init(struct hid_device *hid)
set_bit(FF_RUMBLE, dev->ffbit);
- error = input_ff_create_memless(dev, gaff, hid_gaff_play);
+ error = input_ff_create_mlnx(dev, gaff, hid_gaff_play, FF_UPDATE_RATE);
if (error) {
kfree(gaff);
return error;
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 09/24] Port hid-dr to ff-memless-next
From: Michal Malý @ 2014-04-09 11:21 UTC (permalink / raw)
To: dmitry.torokhov, jkosina; +Cc: linux-input, linux-kernel, Elias Vanderstuyft
In-Reply-To: <1609685.QRL9N9sQvX@sigyn>
Port hid-dr to ff-memless-next
Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
drivers/hid/Kconfig | 2 +-
drivers/hid/hid-dr.c | 59 ++++++++++++++++++++++++++++++++--------------------
2 files changed, 37 insertions(+), 24 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 6e233d2..0ba1962 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -196,7 +196,7 @@ config HID_DRAGONRISE
config DRAGONRISE_FF
bool "DragonRise Inc. force feedback"
depends on HID_DRAGONRISE
- select INPUT_FF_MEMLESS
+ select INPUT_FF_MEMLESS_NEXT
---help---
Say Y here if you want to enable force feedback support for DragonRise Inc.
game controllers.
diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c
index ce06444..b95c676 100644
--- a/drivers/hid/hid-dr.c
+++ b/drivers/hid/hid-dr.c
@@ -31,8 +31,10 @@
#include <linux/slab.h>
#include <linux/hid.h>
#include <linux/module.h>
+#include <linux/input/ff-memless-next.h>
#include "hid-ids.h"
+#define FF_UPDATE_RATE 50
#ifdef CONFIG_DRAGONRISE_FF
@@ -41,38 +43,49 @@ struct drff_device {
};
static int drff_play(struct input_dev *dev, void *data,
- struct ff_effect *effect)
+ const struct mlnx_effect_command *command)
{
struct hid_device *hid = input_get_drvdata(dev);
struct drff_device *drff = data;
+ const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
int strong, weak;
- strong = effect->u.rumble.strong_magnitude;
- weak = effect->u.rumble.weak_magnitude;
+ strong = rumble_force->strong;
+ weak = rumble_force->weak;
dbg_hid("called with 0x%04x 0x%04x", strong, weak);
- if (strong || weak) {
- strong = strong * 0xff / 0xffff;
- weak = weak * 0xff / 0xffff;
-
- /* While reverse engineering this device, I found that when
- this value is set, it causes the strong rumble to function
- at a near maximum speed, so we'll bypass it. */
- if (weak == 0x0a)
- weak = 0x0b;
-
- drff->report->field[0]->value[0] = 0x51;
- drff->report->field[0]->value[1] = 0x00;
- drff->report->field[0]->value[2] = weak;
- drff->report->field[0]->value[4] = strong;
- hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
-
- drff->report->field[0]->value[0] = 0xfa;
- drff->report->field[0]->value[1] = 0xfe;
- } else {
+ switch (command->cmd) {
+ case MLNX_START_RUMBLE:
+ if (strong || weak) {
+ strong = strong * 0xff / 0xffff;
+ weak = weak * 0xff / 0xffff;
+
+ /* While reverse engineering this device, I found that when
+ this value is set, it causes the strong rumble to function
+ at a near maximum speed, so we'll bypass it. */
+ if (weak == 0x0a)
+ weak = 0x0b;
+
+ drff->report->field[0]->value[0] = 0x51;
+ drff->report->field[0]->value[1] = 0x00;
+ drff->report->field[0]->value[2] = weak;
+ drff->report->field[0]->value[4] = strong;
+ hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
+
+ drff->report->field[0]->value[0] = 0xfa;
+ drff->report->field[0]->value[1] = 0xfe;
+ } else {
+ drff->report->field[0]->value[0] = 0xf3;
+ drff->report->field[0]->value[1] = 0x00;
+ }
+ break;
+ case MLNX_STOP_RUMBLE:
drff->report->field[0]->value[0] = 0xf3;
drff->report->field[0]->value[1] = 0x00;
+ break;
+ default:
+ return -EINVAL;
}
drff->report->field[0]->value[2] = 0x00;
@@ -116,7 +129,7 @@ static int drff_init(struct hid_device *hid)
set_bit(FF_RUMBLE, dev->ffbit);
- error = input_ff_create_memless(dev, drff, drff_play);
+ error = input_ff_create_mlnx(dev, drff, drff_play, FF_UPDATE_RATE);
if (error) {
kfree(drff);
return error;
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox