Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH v3 2/3] Input: gpio_keys - convert to use devm_*
From: Dmitry Torokhov @ 2014-04-26  4:43 UTC (permalink / raw)
  To: Andy Shevchenko; +Cc: Linus Walleij, linux-input, linux-kernel
In-Reply-To: <1398442937-15309-3-git-send-email-andriy.shevchenko@linux.intel.com>

On Fri, Apr 25, 2014 at 07:22:16PM +0300, Andy Shevchenko wrote:
> This makes the error handling much more simpler than open-coding everything and
> in addition makes the probe function smaller an tidier.
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> ---
>  drivers/input/keyboard/gpio_keys.c | 75 +++++++++++++-------------------------
>  1 file changed, 25 insertions(+), 50 deletions(-)
> 
> diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
> index 209d4c6..8791d94 100644
> --- a/drivers/input/keyboard/gpio_keys.c
> +++ b/drivers/input/keyboard/gpio_keys.c
> @@ -47,7 +47,7 @@ struct gpio_keys_drvdata {
>  	const struct gpio_keys_platform_data *pdata;
>  	struct input_dev *input;
>  	struct mutex disable_lock;
> -	struct gpio_button_data data[0];
> +	struct gpio_button_data *data;
>  };
>  
>  /*
> @@ -577,25 +577,22 @@ gpio_keys_get_devtree_pdata(struct device *dev)
>  	int i;
>  
>  	node = dev->of_node;
> -	if (!node) {
> -		error = -ENODEV;
> -		goto err_out;
> -	}
> +	if (!node)
> +		return ERR_PTR(-ENODEV);
>  
>  	nbuttons = of_get_child_count(node);
> -	if (nbuttons == 0) {
> -		error = -ENODEV;
> -		goto err_out;
> -	}
> +	if (nbuttons == 0)
> +		return ERR_PTR(-ENODEV);
>  
> -	pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button),
> -			GFP_KERNEL);
> -	if (!pdata) {
> -		error = -ENOMEM;
> -		goto err_out;
> -	}
> +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata)
> +		return ERR_PTR(-ENOMEM);
> +
> +	pdata->buttons = devm_kcalloc(dev, nbuttons, sizeof (*button),
> +				      GFP_KERNEL);
> +	if (!pdata->buttons)
> +		return ERR_PTR(-ENOMEM);

Why are we splitting the allocation in 2?

>  
> -	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
>  	pdata->nbuttons = nbuttons;
>  
>  	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
> @@ -618,7 +615,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
>  				dev_err(dev,
>  					"Failed to get gpio flags, error: %d\n",
>  					error);
> -			goto err_free_pdata;
> +			return ERR_PTR(error);
>  		}
>  
>  		button = &pdata->buttons[i++];
> @@ -629,8 +626,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
>  		if (of_property_read_u32(pp, "linux,code", &button->code)) {
>  			dev_err(dev, "Button without keycode: 0x%x\n",
>  				button->gpio);
> -			error = -EINVAL;
> -			goto err_free_pdata;
> +			return ERR_PTR(-EINVAL);
>  		}
>  
>  		button->desc = of_get_property(pp, "label", NULL);
> @@ -645,17 +641,10 @@ gpio_keys_get_devtree_pdata(struct device *dev)
>  			button->debounce_interval = 5;
>  	}
>  
> -	if (pdata->nbuttons == 0) {
> -		error = -EINVAL;
> -		goto err_free_pdata;
> -	}
> +	if (pdata->nbuttons == 0)
> +		return ERR_PTR(-EINVAL);
>  
>  	return pdata;
> -
> -err_free_pdata:
> -	kfree(pdata);
> -err_out:
> -	return ERR_PTR(error);
>  }
>  
>  static struct of_device_id gpio_keys_of_match[] = {
> @@ -699,16 +688,18 @@ static int gpio_keys_probe(struct platform_device *pdev)
>  			return PTR_ERR(pdata);
>  	}
>  
> -	ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
> -			pdata->nbuttons * sizeof(struct gpio_button_data),
> -			GFP_KERNEL);
> -	input = input_allocate_device();
> +	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
> +	input = devm_input_allocate_device(dev);
>  	if (!ddata || !input) {
>  		dev_err(dev, "failed to allocate state\n");
> -		error = -ENOMEM;
> -		goto fail1;
> +		return -ENOMEM;
>  	}
>  
> +	ddata->data = devm_kcalloc(dev, pdata->nbuttons,  sizeof(*ddata->data),
> +				   GFP_KERNEL);
> +	if (!ddata->data)
> +		return -ENOMEM;
> +

Same here. I dropped the separate allocations and applied.

Thanks.

-- 
Dmitry

^ permalink raw reply

* [PATCH RESEND] input: dts: Add commonly used event types
From: Alexander Shiyan @ 2014-04-26  5:37 UTC (permalink / raw)
  To: linux-input-u79uwXL29TY76Z2rM5mHXA
  Cc: Dmitry Torokhov, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Alexander Shiyan

Patch adds commonly used event types (EV_KEY and EV_SW) to
devicetree bindings header for input subsystem.

Signed-off-by: Alexander Shiyan <shc_work-JGs/UdohzUI@public.gmane.org>
---
 include/dt-bindings/input/input.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/dt-bindings/input/input.h b/include/dt-bindings/input/input.h
index 042e7b3..3a141d92 100644
--- a/include/dt-bindings/input/input.h
+++ b/include/dt-bindings/input/input.h
@@ -9,6 +9,9 @@
 #ifndef _DT_BINDINGS_INPUT_INPUT_H
 #define _DT_BINDINGS_INPUT_INPUT_H
 
+#define EV_KEY			0x01
+#define EV_SW			0x05
+
 #define KEY_RESERVED		0
 #define KEY_ESC			1
 #define KEY_1			2
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v2] input: gpio-beeper: Simplify GPIO handling
From: Alexander Shiyan @ 2014-04-26  5:46 UTC (permalink / raw)
  To: linux-input; +Cc: Dmitry Torokhov, Alexander Shiyan

This patch simplifies GPIO handling in the driver by using GPIO
functions based on descriptors. As a result this driver now can
be used for boards without DT support.

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
 drivers/input/misc/Kconfig       |  2 +-
 drivers/input/misc/gpio-beeper.c | 34 +++++++++++++++-------------------
 2 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 5928ea7..2ff4425 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -224,7 +224,7 @@ config INPUT_GP2A
 
 config INPUT_GPIO_BEEPER
 	tristate "Generic GPIO Beeper support"
-	depends on OF_GPIO
+	depends on GPIOLIB
 	help
 	  Say Y here if you have a beeper connected to a GPIO pin.
 
diff --git a/drivers/input/misc/gpio-beeper.c b/drivers/input/misc/gpio-beeper.c
index b757435..4b90877 100644
--- a/drivers/input/misc/gpio-beeper.c
+++ b/drivers/input/misc/gpio-beeper.c
@@ -1,7 +1,7 @@
 /*
  * Generic GPIO beeper driver
  *
- * Copyright (C) 2013 Alexander Shiyan <shc_work@mail.ru>
+ * Copyright (C) 2013-2014 Alexander Shiyan <shc_work@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
@@ -11,7 +11,7 @@
 
 #include <linux/input.h>
 #include <linux/module.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio.h>
 #include <linux/workqueue.h>
 #include <linux/platform_device.h>
 
@@ -19,14 +19,13 @@
 
 struct gpio_beeper {
 	struct work_struct	work;
-	int			gpio;
-	bool			active_low;
-	bool			beeping;
+	struct gpio_desc	*desc;
+	int			beeping;
 };
 
-static void gpio_beeper_toggle(struct gpio_beeper *beep, bool on)
+static void gpio_beeper_toggle(struct gpio_beeper *beep, int val)
 {
-	gpio_set_value_cansleep(beep->gpio, on ^ beep->active_low);
+	gpiod_set_value_cansleep(beep->desc, val);
 }
 
 static void gpio_beeper_work(struct work_struct *work)
@@ -59,24 +58,24 @@ static void gpio_beeper_close(struct input_dev *input)
 	struct gpio_beeper *beep = input_get_drvdata(input);
 
 	cancel_work_sync(&beep->work);
-	gpio_beeper_toggle(beep, false);
+	gpio_beeper_toggle(beep, 0);
 }
 
 static int gpio_beeper_probe(struct platform_device *pdev)
 {
 	struct gpio_beeper *beep;
-	enum of_gpio_flags flags;
 	struct input_dev *input;
-	unsigned long gflags;
 	int err;
 
 	beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL);
 	if (!beep)
 		return -ENOMEM;
 
-	beep->gpio = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
-	if (!gpio_is_valid(beep->gpio))
-		return beep->gpio;
+	beep->desc = devm_gpiod_get(&pdev->dev, NULL);
+	if (!beep->desc)
+		return -EINVAL;
+	if (IS_ERR(beep->desc))
+		return PTR_ERR(beep->desc);
 
 	input = devm_input_allocate_device(&pdev->dev);
 	if (!input)
@@ -94,10 +93,7 @@ static int gpio_beeper_probe(struct platform_device *pdev)
 
 	input_set_capability(input, EV_SND, SND_BELL);
 
-	beep->active_low = flags & OF_GPIO_ACTIVE_LOW;
-	gflags = beep->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-
-	err = devm_gpio_request_one(&pdev->dev, beep->gpio, gflags, pdev->name);
+	err = gpiod_direction_output(beep->desc, 0);
 	if (err)
 		return err;
 
@@ -106,7 +102,7 @@ static int gpio_beeper_probe(struct platform_device *pdev)
 	return input_register_device(input);
 }
 
-static struct of_device_id gpio_beeper_of_match[] = {
+static struct of_device_id __maybe_unused gpio_beeper_of_match[] = {
 	{ .compatible = BEEPER_MODNAME, },
 	{ }
 };
@@ -116,7 +112,7 @@ static struct platform_driver gpio_beeper_platform_driver = {
 	.driver	= {
 		.name		= BEEPER_MODNAME,
 		.owner		= THIS_MODULE,
-		.of_match_table	= gpio_beeper_of_match,
+		.of_match_table	= of_match_ptr(gpio_beeper_of_match),
 	},
 	.probe	= gpio_beeper_probe,
 };
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH RESEND 2/2] input: gpio_keys: Convert to devm-* API
From: Alexander Shiyan @ 2014-04-26  5:53 UTC (permalink / raw)
  To: linux-input; +Cc: Dmitry Torokhov, Alexander Shiyan
In-Reply-To: <1398491594-2004-1-git-send-email-shc_work@mail.ru>

Replace existing resource handling in the driver with managed
device resource, this ensures more consistent error values and
simplifies error paths.
kzalloc -> devm_kzalloc
gpio_request_one -> devm_gpio_request_one
input_allocate_device -> devm_input_allocate_device

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
 drivers/input/keyboard/gpio_keys.c | 96 +++++++++++---------------------------
 1 file changed, 28 insertions(+), 68 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 2db1324..c4bc6e4 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -433,7 +433,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
 	struct device *dev = &pdev->dev;
 	irq_handler_t isr;
 	unsigned long irqflags;
-	int irq, error;
+	int error;
 
 	bdata->input = input;
 	bdata->button = button;
@@ -441,7 +441,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
 
 	if (gpio_is_valid(button->gpio)) {
 
-		error = gpio_request_one(button->gpio, GPIOF_IN, desc);
+		error = devm_gpio_request_one(&pdev->dev, button->gpio,
+					      GPIOF_IN, desc);
 		if (error < 0) {
 			dev_err(dev, "Failed to request GPIO %d, error %d\n",
 				button->gpio, error);
@@ -457,15 +458,13 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
 						button->debounce_interval;
 		}
 
-		irq = gpio_to_irq(button->gpio);
-		if (irq < 0) {
-			error = irq;
+		bdata->irq = gpio_to_irq(button->gpio);
+		if (bdata->irq < 0) {
 			dev_err(dev,
 				"Unable to get irq number for GPIO %d, error %d\n",
-				button->gpio, error);
-			goto fail;
+				button->gpio, bdata->irq);
+			return bdata->irq;
 		}
-		bdata->irq = irq;
 
 		INIT_WORK(&bdata->work, gpio_keys_gpio_work_func);
 		setup_timer(&bdata->timer,
@@ -507,16 +506,10 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
 	if (error < 0) {
 		dev_err(dev, "Unable to claim irq %d; error %d\n",
 			bdata->irq, error);
-		goto fail;
+		return error;
 	}
 
 	return 0;
-
-fail:
-	if (gpio_is_valid(button->gpio))
-		gpio_free(button->gpio);
-
-	return error;
 }
 
 static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata)
@@ -573,28 +566,20 @@ gpio_keys_get_devtree_pdata(struct device *dev)
 	struct device_node *node, *pp;
 	struct gpio_keys_platform_data *pdata;
 	struct gpio_keys_button *button;
-	int error;
-	int nbuttons;
-	int i;
+	int i, nbuttons;
 
 	node = dev->of_node;
-	if (!node) {
-		error = -ENODEV;
-		goto err_out;
-	}
+	if (!node)
+		return ERR_PTR(-ENODEV);
 
 	nbuttons = of_get_child_count(node);
-	if (nbuttons == 0) {
-		error = -ENODEV;
-		goto err_out;
-	}
+	if (nbuttons == 0)
+		return ERR_PTR(-ENODEV);
 
-	pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button),
-			GFP_KERNEL);
-	if (!pdata) {
-		error = -ENOMEM;
-		goto err_out;
-	}
+	pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons * sizeof(*button),
+			     GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
 
 	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
 	pdata->nbuttons = nbuttons;
@@ -614,12 +599,11 @@ gpio_keys_get_devtree_pdata(struct device *dev)
 
 		gpio = of_get_gpio_flags(pp, 0, &flags);
 		if (gpio < 0) {
-			error = gpio;
-			if (error != -EPROBE_DEFER)
+			if (gpio != -EPROBE_DEFER)
 				dev_err(dev,
 					"Failed to get gpio flags, error: %d\n",
-					error);
-			goto err_free_pdata;
+					gpio);
+			return ERR_PTR(gpio);
 		}
 
 		button = &pdata->buttons[i++];
@@ -630,8 +614,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
 		if (of_property_read_u32(pp, "linux,code", &button->code)) {
 			dev_err(dev, "Button without keycode: 0x%x\n",
 				button->gpio);
-			error = -EINVAL;
-			goto err_free_pdata;
+			return ERR_PTR(-EINVAL);
 		}
 
 		button->desc = of_get_property(pp, "label", NULL);
@@ -646,17 +629,10 @@ gpio_keys_get_devtree_pdata(struct device *dev)
 			button->debounce_interval = 5;
 	}
 
-	if (pdata->nbuttons == 0) {
-		error = -EINVAL;
-		goto err_free_pdata;
-	}
+	if (!pdata->nbuttons)
+		return ERR_PTR(-EINVAL);
 
 	return pdata;
-
-err_free_pdata:
-	kfree(pdata);
-err_out:
-	return ERR_PTR(error);
 }
 
 static struct of_device_id gpio_keys_of_match[] = {
@@ -681,8 +657,6 @@ static void gpio_remove_key(struct gpio_button_data *bdata)
 	if (bdata->timer_debounce)
 		del_timer_sync(&bdata->timer);
 	cancel_work_sync(&bdata->work);
-	if (gpio_is_valid(bdata->button->gpio))
-		gpio_free(bdata->button->gpio);
 }
 
 static int gpio_keys_probe(struct platform_device *pdev)
@@ -700,14 +674,13 @@ static int gpio_keys_probe(struct platform_device *pdev)
 			return PTR_ERR(pdata);
 	}
 
-	ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
-			pdata->nbuttons * sizeof(struct gpio_button_data),
-			GFP_KERNEL);
-	input = input_allocate_device();
+	ddata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_keys_drvdata) +
+			     pdata->nbuttons * sizeof(struct gpio_button_data),
+			     GFP_KERNEL);
+	input = devm_input_allocate_device(&pdev->dev);
 	if (!ddata || !input) {
 		dev_err(dev, "failed to allocate state\n");
-		error = -ENOMEM;
-		goto fail1;
+		return -ENOMEM;
 	}
 
 	ddata->pdata = pdata;
@@ -768,13 +741,6 @@ static int gpio_keys_probe(struct platform_device *pdev)
 	while (--i >= 0)
 		gpio_remove_key(&ddata->data[i]);
 
- fail1:
-	input_free_device(input);
-	kfree(ddata);
-	/* If we have no platform data, we allocated pdata dynamically. */
-	if (!dev_get_platdata(&pdev->dev))
-		kfree(pdata);
-
 	return error;
 }
 
@@ -793,12 +759,6 @@ static int gpio_keys_remove(struct platform_device *pdev)
 
 	input_unregister_device(input);
 
-	/* If we have no platform data, we allocated pdata dynamically. */
-	if (!dev_get_platdata(&pdev->dev))
-		kfree(ddata->pdata);
-
-	kfree(ddata);
-
 	return 0;
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH RESEND 1/2] input: gpio_keys_polled: Convert to devm-* API
From: Alexander Shiyan @ 2014-04-26  5:53 UTC (permalink / raw)
  To: linux-input; +Cc: Dmitry Torokhov, Alexander Shiyan

Replace existing resource handling in the driver with managed
device resource, this ensures more consistent error values and
simplifies error paths.
kzalloc -> devm_kzalloc
gpio_request_one -> devm_gpio_request_one

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
 drivers/input/keyboard/gpio_keys_polled.c | 87 ++++++++-----------------------
 1 file changed, 23 insertions(+), 64 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index e571e19..04db0a5 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -108,9 +108,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
 	struct device_node *node, *pp;
 	struct gpio_keys_platform_data *pdata;
 	struct gpio_keys_button *button;
-	int error;
-	int nbuttons;
-	int i;
+	int i, nbuttons;
 
 	node = dev->of_node;
 	if (!node)
@@ -120,12 +118,10 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
 	if (nbuttons == 0)
 		return NULL;
 
-	pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button),
-			GFP_KERNEL);
-	if (!pdata) {
-		error = -ENOMEM;
-		goto err_out;
-	}
+	pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons * sizeof(*button),
+			     GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
 
 	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
 	pdata->nbuttons = nbuttons;
@@ -146,12 +142,11 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
 
 		gpio = of_get_gpio_flags(pp, 0, &flags);
 		if (gpio < 0) {
-			error = gpio;
-			if (error != -EPROBE_DEFER)
+			if (gpio != -EPROBE_DEFER)
 				dev_err(dev,
 					"Failed to get gpio flags, error: %d\n",
-					error);
-			goto err_free_pdata;
+					gpio);
+			return ERR_PTR(gpio);
 		}
 
 		button = &pdata->buttons[i++];
@@ -162,8 +157,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
 		if (of_property_read_u32(pp, "linux,code", &button->code)) {
 			dev_err(dev, "Button without keycode: 0x%x\n",
 				button->gpio);
-			error = -EINVAL;
-			goto err_free_pdata;
+			return ERR_PTR(-EINVAL);
 		}
 
 		button->desc = of_get_property(pp, "label", NULL);
@@ -178,17 +172,10 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
 			button->debounce_interval = 5;
 	}
 
-	if (pdata->nbuttons == 0) {
-		error = -EINVAL;
-		goto err_free_pdata;
-	}
+	if (!pdata->nbuttons)
+		return ERR_PTR(-EINVAL);
 
 	return pdata;
-
-err_free_pdata:
-	kfree(pdata);
-err_out:
-	return ERR_PTR(error);
 }
 
 static struct of_device_id gpio_keys_polled_of_match[] = {
@@ -228,24 +215,21 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
 
 	if (!pdata->poll_interval) {
 		dev_err(dev, "missing poll_interval value\n");
-		error = -EINVAL;
-		goto err_free_pdata;
+		return -EINVAL;
 	}
 
-	bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
-		       pdata->nbuttons * sizeof(struct gpio_keys_button_data),
-		       GFP_KERNEL);
+	bdev = devm_kzalloc(&pdev->dev, sizeof(struct gpio_keys_polled_dev) +
+			pdata->nbuttons * sizeof(struct gpio_keys_button_data),
+			GFP_KERNEL);
 	if (!bdev) {
 		dev_err(dev, "no memory for private data\n");
-		error = -ENOMEM;
-		goto err_free_pdata;
+		return -ENOMEM;
 	}
 
 	poll_dev = input_allocate_polled_device();
 	if (!poll_dev) {
 		dev_err(dev, "no memory for polled device\n");
-		error = -ENOMEM;
-		goto err_free_bdev;
+		return -ENOMEM;
 	}
 
 	poll_dev->private = bdev;
@@ -278,15 +262,15 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
 		if (button->wakeup) {
 			dev_err(dev, DRV_NAME " does not support wakeup\n");
 			error = -EINVAL;
-			goto err_free_gpio;
+			goto err_out;
 		}
 
-		error = gpio_request_one(gpio, GPIOF_IN,
-					 button->desc ?: DRV_NAME);
+		error = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_IN,
+					      button->desc ? : DRV_NAME);
 		if (error) {
 			dev_err(dev, "unable to claim gpio %u, err=%d\n",
 				gpio, error);
-			goto err_free_gpio;
+			goto err_out;
 		}
 
 		bdata->can_sleep = gpio_cansleep(gpio);
@@ -306,7 +290,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
 	if (error) {
 		dev_err(dev, "unable to register polled device, err=%d\n",
 			error);
-		goto err_free_gpio;
+		goto err_out;
 	}
 
 	/* report initial state of the buttons */
@@ -316,45 +300,20 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
 
 	return 0;
 
-err_free_gpio:
-	while (--i >= 0)
-		gpio_free(pdata->buttons[i].gpio);
-
+err_out:
 	input_free_polled_device(poll_dev);
 
-err_free_bdev:
-	kfree(bdev);
-
-err_free_pdata:
-	/* If we have no platform_data, we allocated pdata dynamically.  */
-	if (!dev_get_platdata(&pdev->dev))
-		kfree(pdata);
-
 	return error;
 }
 
 static int gpio_keys_polled_remove(struct platform_device *pdev)
 {
 	struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
-	const struct gpio_keys_platform_data *pdata = bdev->pdata;
-	int i;
 
 	input_unregister_polled_device(bdev->poll_dev);
 
-	for (i = 0; i < pdata->nbuttons; i++)
-		gpio_free(pdata->buttons[i].gpio);
-
 	input_free_polled_device(bdev->poll_dev);
 
-	/*
-	 * If we had no platform_data, we allocated pdata dynamically and
-	 * must free it here.
-	 */
-	if (!dev_get_platdata(&pdev->dev))
-		kfree(pdata);
-
-	kfree(bdev);
-
 	return 0;
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH v3 02/24] input: Port arizona-haptics to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

Port arizona-haptics to ff-memless-next

Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
 drivers/input/misc/Kconfig           |  2 +-
 drivers/input/misc/arizona-haptics.c | 39 +++++++++++++++++++++++-------------
 2 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 5928ea7..f669cc7 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -75,7 +75,7 @@ config INPUT_AD714X_SPI
 config INPUT_ARIZONA_HAPTICS
 	tristate "Arizona haptics support"
 	depends on MFD_ARIZONA && SND_SOC
-	select INPUT_FF_MEMLESS
+	select INPUT_FF_MEMLESS_NEXT
 	help
 	  Say Y to enable support for the haptics module in Arizona CODECs.
 
diff --git a/drivers/input/misc/arizona-haptics.c b/drivers/input/misc/arizona-haptics.c
index ef2e281..b4707cc 100644
--- a/drivers/input/misc/arizona-haptics.c
+++ b/drivers/input/misc/arizona-haptics.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
+#include <linux/input/ff-memless-next.h>
 #include <linux/slab.h>
 
 #include <sound/soc.h>
@@ -22,6 +23,8 @@
 #include <linux/mfd/arizona/pdata.h>
 #include <linux/mfd/arizona/registers.h>
 
+#define FF_UPDATE_RATE 50
+
 struct arizona_haptics {
 	struct arizona *arizona;
 	struct input_dev *input_dev;
@@ -108,29 +111,37 @@ static void arizona_haptics_work(struct work_struct *work)
 }
 
 static int arizona_haptics_play(struct input_dev *input, void *data,
-				struct ff_effect *effect)
+				const struct mlnx_effect_command *command)
 {
 	struct arizona_haptics *haptics = input_get_drvdata(input);
 	struct arizona *arizona = haptics->arizona;
+	const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
 
 	if (!arizona->dapm) {
 		dev_err(arizona->dev, "No DAPM context\n");
 		return -EBUSY;
 	}
 
-	if (effect->u.rumble.strong_magnitude) {
-		/* Scale the magnitude into the range the device supports */
-		if (arizona->pdata.hap_act) {
-			haptics->intensity =
-				effect->u.rumble.strong_magnitude >> 9;
-			if (effect->direction < 0x8000)
-				haptics->intensity += 0x7f;
+	switch (command->cmd) {
+	case MLNX_START_RUMBLE:
+		if (rumble_force->strong) {
+			/* Scale the magnitude into the range the device supports */
+			if (arizona->pdata.hap_act) {
+				haptics->intensity = rumble_force->strong >> 9;
+				if (rumble_force->strong_dir < 0x8000)
+					haptics->intensity += 0x7f;
+			} else {
+				haptics->intensity = rumble_force->strong >> 8;
+			}
 		} else {
-			haptics->intensity =
-				effect->u.rumble.strong_magnitude >> 8;
+			haptics->intensity = 0;
 		}
-	} else {
+		break;
+	case MLNX_STOP_RUMBLE:
 		haptics->intensity = 0;
+		break;
+	default:
+		return -EINVAL;
 	}
 
 	schedule_work(&haptics->work);
@@ -183,10 +194,10 @@ static int arizona_haptics_probe(struct platform_device *pdev)
 	haptics->input_dev->close = arizona_haptics_close;
 	__set_bit(FF_RUMBLE, haptics->input_dev->ffbit);
 
-	ret = input_ff_create_memless(haptics->input_dev, NULL,
-				      arizona_haptics_play);
+	ret = input_ff_create_mlnx(haptics->input_dev, NULL,
+				   arizona_haptics_play, FF_UPDATE_RATE);
 	if (ret < 0) {
-		dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n",
+		dev_err(arizona->dev, "input_ff_create_mlnx() failed: %d\n",
 			ret);
 		goto err_ialloc;
 	}
-- 
1.9.2

^ permalink raw reply related

* [PATCH v3 03/24] input: Port twl4030-vibra to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

Port twl4030-vibra to ff-memless-next

Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
 drivers/input/misc/Kconfig         |  2 +-
 drivers/input/misc/twl4030-vibra.c | 31 +++++++++++++++++++++++++------
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index f669cc7..817156f 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -407,7 +407,7 @@ config INPUT_TWL4030_VIBRA
 	tristate "Support for TWL4030 Vibrator"
 	depends on TWL4030_CORE
 	select MFD_TWL4030_AUDIO
-	select INPUT_FF_MEMLESS
+	select INPUT_FF_MEMLESS_NEXT
 	help
 	  This option enables support for TWL4030 Vibrator Driver.
 
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index 960ef2a..5274ad2 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -32,9 +32,11 @@
 #include <linux/mfd/twl4030-audio.h>
 #include <linux/input.h>
 #include <linux/slab.h>
+#include <linux/input/ff-memless-next.h>
 
 /* MODULE ID2 */
 #define LEDEN		0x00
+#define FF_UPDATE_RATE	50
 
 /* ForceFeedback */
 #define EFFECT_DIR_180_DEG	0x8000 /* range is 0 - 0xFFFF */
@@ -134,14 +136,31 @@ static void vibra_play_work(struct work_struct *work)
 /*** Input/ForceFeedback ***/
 
 static int vibra_play(struct input_dev *input, void *data,
-		      struct ff_effect *effect)
+		      const struct mlnx_effect_command *command)
 {
 	struct vibra_info *info = input_get_drvdata(input);
+	const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
+
+	switch (command->cmd) {
+	case MLNX_START_RUMBLE:
+		if (command->u.rumble_force.strong) {
+			info->speed = rumble_force->strong >> 8;
+			info->direction = rumble_force->strong_dir < EFFECT_DIR_180_DEG ?
+					  0 : 1;
+		} else {
+			info->speed = rumble_force->weak >> 9;
+			info->direction = rumble_force->weak_dir < EFFECT_DIR_180_DEG ?
+					  0 : 1;
+		}
+		break;
+	case MLNX_STOP_RUMBLE:
+		info->speed = 0;
+		info->direction = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
 
-	info->speed = effect->u.rumble.strong_magnitude >> 8;
-	if (!info->speed)
-		info->speed = effect->u.rumble.weak_magnitude >> 9;
-	info->direction = effect->direction < EFFECT_DIR_180_DEG ? 0 : 1;
 	schedule_work(&info->play_work);
 	return 0;
 }
@@ -227,7 +246,7 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
 	info->input_dev->close = twl4030_vibra_close;
 	__set_bit(FF_RUMBLE, info->input_dev->ffbit);
 
-	ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
+	ret = input_ff_create_mlnx(info->input_dev, NULL, vibra_play, FF_UPDATE_RATE);
 	if (ret < 0) {
 		dev_dbg(&pdev->dev, "couldn't register vibrator to FF\n");
 		return ret;
-- 
1.9.2

^ permalink raw reply related

* [PATCH v4 04/24] input: Port twl6040-vibra to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

Port twl6040-vibra to ff-memless-next

Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
 drivers/input/misc/Kconfig         |  2 +-
 drivers/input/misc/twl6040-vibra.c | 27 ++++++++++++++++++++++-----
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 817156f..b9cbb91 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -417,7 +417,7 @@ config INPUT_TWL4030_VIBRA
 config INPUT_TWL6040_VIBRA
 	tristate "Support for TWL6040 Vibrator"
 	depends on TWL6040_CORE
-	select INPUT_FF_MEMLESS
+	select INPUT_FF_MEMLESS_NEXT
 	help
 	  This option enables support for TWL6040 Vibrator Driver.
 
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
index 77dc23b..7440a74 100644
--- a/drivers/input/misc/twl6040-vibra.c
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -30,12 +30,14 @@
 #include <linux/of.h>
 #include <linux/workqueue.h>
 #include <linux/input.h>
+#include <linux/input/ff-memless-next.h>
 #include <linux/mfd/twl6040.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/regulator/consumer.h>
 
 #define EFFECT_DIR_180_DEG	0x8000
+#define FF_UPDATE_RATE		50
 
 /* Recommended modulation index 85% */
 #define TWL6040_VIBRA_MOD	85
@@ -197,9 +199,10 @@ static void vibra_play_work(struct work_struct *work)
 }
 
 static int vibra_play(struct input_dev *input, void *data,
-		      struct ff_effect *effect)
+		      const struct mlnx_effect_command *command)
 {
 	struct vibra_info *info = input_get_drvdata(input);
+	const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
 	int ret;
 
 	/* Do not allow effect, while the routing is set to use audio */
@@ -209,9 +212,23 @@ static int vibra_play(struct input_dev *input, void *data,
 		return -EBUSY;
 	}
 
-	info->weak_speed = effect->u.rumble.weak_magnitude;
-	info->strong_speed = effect->u.rumble.strong_magnitude;
-	info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
+	switch (command->cmd) {
+	case MLNX_START_RUMBLE:
+		info->weak_speed = rumble_force->weak;
+		info->strong_speed = rumble_force->strong;
+		if (info->strong_speed >= info->weak_speed)
+			info->direction = rumble_force->strong_dir < EFFECT_DIR_180_DEG ? 1 : -1;
+		else
+			info->direction = rumble_force->weak_dir < EFFECT_DIR_180_DEG ? 1 : -1;
+		break;
+	case MLNX_STOP_RUMBLE:
+		info->weak_speed = 0;
+		info->strong_speed = 0;
+		info->direction = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	ret = queue_work(info->workqueue, &info->play_work);
 	if (!ret) {
@@ -367,7 +384,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
 	info->input_dev->close = twl6040_vibra_close;
 	__set_bit(FF_RUMBLE, info->input_dev->ffbit);
 
-	ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
+	ret = input_ff_create_mlnx(info->input_dev, NULL, vibra_play, FF_UPDATE_RATE);
 	if (ret < 0) {
 		dev_err(info->dev, "couldn't register vibrator to FF\n");
 		goto err_ialloc;
-- 
1.9.2

^ permalink raw reply related

* [PATCH v3 05/24] input: Port max8997_haptic to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

Port max8997_haptic to ff-memless-next

Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
 drivers/input/misc/Kconfig          |  2 +-
 drivers/input/misc/max8997_haptic.c | 25 +++++++++++++++++++------
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index b9cbb91..a89dc22 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -157,7 +157,7 @@ config INPUT_MAX8925_ONKEY
 config INPUT_MAX8997_HAPTIC
 	tristate "MAXIM MAX8997 haptic controller support"
 	depends on PWM && MFD_MAX8997
-	select INPUT_FF_MEMLESS
+	select INPUT_FF_MEMLESS_NEXT
 	help
 	  This option enables device driver support for the haptic controller
 	  on MAXIM MAX8997 chip. This driver supports ff-memless interface
diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index 1fea548..029ac8b 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -31,6 +31,7 @@
 #include <linux/mfd/max8997-private.h>
 #include <linux/mfd/max8997.h>
 #include <linux/regulator/consumer.h>
+#include <linux/input/ff-memless-next.h>
 
 /* Haptic configuration 2 register */
 #define MAX8997_MOTOR_TYPE_SHIFT	7
@@ -43,6 +44,8 @@
 #define MAX8997_SIG_DUTY_SHIFT		2
 #define MAX8997_PWM_DUTY_SHIFT		0
 
+#define FF_UPDATE_RATE 50
+
 struct max8997_haptic {
 	struct device *dev;
 	struct i2c_client *client;
@@ -219,13 +222,23 @@ static void max8997_haptic_play_effect_work(struct work_struct *work)
 }
 
 static int max8997_haptic_play_effect(struct input_dev *dev, void *data,
-				  struct ff_effect *effect)
+				  const struct mlnx_effect_command *command)
 {
 	struct max8997_haptic *chip = input_get_drvdata(dev);
+	const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
 
-	chip->level = effect->u.rumble.strong_magnitude;
-	if (!chip->level)
-		chip->level = effect->u.rumble.weak_magnitude;
+	switch (command->cmd) {
+	case MLNX_START_RUMBLE:
+		chip->level = rumble_force->strong;
+		if (!chip->level)
+			chip->level = rumble_force->weak;
+		break;
+	case MLNX_STOP_RUMBLE:
+		chip->level = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	schedule_work(&chip->work);
 
@@ -319,8 +332,8 @@ static int max8997_haptic_probe(struct platform_device *pdev)
 	input_set_drvdata(input_dev, chip);
 	input_set_capability(input_dev, EV_FF, FF_RUMBLE);
 
-	error = input_ff_create_memless(input_dev, NULL,
-				max8997_haptic_play_effect);
+	error = input_ff_create_mlnx(input_dev, NULL,
+				max8997_haptic_play_effect, FF_UPDATE_RATE);
 	if (error) {
 		dev_err(&pdev->dev,
 			"unable to create FF device, error: %d\n",
-- 
1.9.2

^ permalink raw reply related

* [PATCH v3 06/24] input: Port pm8xxx-vibrator to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

Port pm8xxx-vibrator to ff-memless-next

Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
 drivers/input/misc/Kconfig           |  2 +-
 drivers/input/misc/pm8xxx-vibrator.c | 28 +++++++++++++++++++---------
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index a89dc22..7b962e4 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -108,7 +108,7 @@ config INPUT_PCSPKR
 config INPUT_PM8XXX_VIBRATOR
 	tristate "Qualcomm PM8XXX vibrator support"
 	depends on MFD_PM8XXX
-	select INPUT_FF_MEMLESS
+	select INPUT_FF_MEMLESS_NEXT
 	help
 	  This option enables device driver support for the vibrator
 	  on Qualcomm PM8xxx chip. This driver supports ff-memless interface
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
index 6a915ba..1796f4f 100644
--- a/drivers/input/misc/pm8xxx-vibrator.c
+++ b/drivers/input/misc/pm8xxx-vibrator.c
@@ -17,6 +17,7 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/regmap.h>
+#include <linux/input/ff-memless-next.h>
 
 #define VIB_DRV			0x4A
 
@@ -29,7 +30,7 @@
 #define VIB_MAX_LEVELS		(VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV)
 
 #define MAX_FF_SPEED		0xff
-
+#define FF_UPDATE_RATE		50
 /**
  * struct pm8xxx_vib - structure to hold vibrator data
  * @vib_input_dev: input device supporting force feedback
@@ -128,14 +129,23 @@ static void pm8xxx_vib_close(struct input_dev *dev)
  * Currently this driver supports only rumble effects.
  */
 static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data,
-				  struct ff_effect *effect)
+				  const struct mlnx_command *command)
 {
 	struct pm8xxx_vib *vib = input_get_drvdata(dev);
-
-	vib->speed = effect->u.rumble.strong_magnitude >> 8;
-	if (!vib->speed)
-		vib->speed = effect->u.rumble.weak_magnitude >> 9;
-
+	const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
+
+	switch (command->cmd) {
+	case MLNX_START_RUMBLE:
+		vib->speed = rumble_force->strong >> 8;
+		if (!vib->speed)
+			vib->speed = rumble_force->weak >> 9;
+		break;
+	case MLNX_STOP_RUMBLE:
+		vib->speed = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
 	schedule_work(&vib->work);
 
 	return 0;
@@ -181,8 +191,8 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
 	input_set_drvdata(input_dev, vib);
 	input_set_capability(vib->vib_input_dev, EV_FF, FF_RUMBLE);
 
-	error = input_ff_create_memless(input_dev, NULL,
-					pm8xxx_vib_play_effect);
+	error = input_ff_create_mlnx(input_dev, NULL,
+				     pm8xxx_vib_play_effect, FF_UPDATE_RATE);
 	if (error) {
 		dev_err(&pdev->dev,
 			"couldn't register vibrator as FF device\n");
-- 
1.9.2

^ permalink raw reply related

* [PATCH v3 07/24] hid: Port hid-axff to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

Port hid-axff to ff-memless-next

Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
 drivers/hid/Kconfig    |  2 +-
 drivers/hid/hid-axff.c | 32 +++++++++++++++++++++++---------
 2 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 7af9d0b..e076627 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -106,7 +106,7 @@ config HID_ACRUX
 config HID_ACRUX_FF
 	bool "ACRUX force feedback support"
 	depends on HID_ACRUX
-	select INPUT_FF_MEMLESS
+	select INPUT_FF_MEMLESS_NEXT
 	---help---
 	Say Y here if you want to enable force feedback support for ACRUX
 	game controllers.
diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c
index a594e47..7fbfcbc 100644
--- a/drivers/hid/hid-axff.c
+++ b/drivers/hid/hid-axff.c
@@ -31,31 +31,45 @@
 #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_HID_ACRUX_FF
 
 struct axff_device {
 	struct hid_report *report;
 };
 
-static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
+static int axff_play(struct input_dev *dev, void *data,
+		     const struct mlnx_effect_command *command)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct axff_device *axff = data;
 	struct hid_report *report = axff->report;
+	const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
 	int field_count = 0;
 	int left, right;
 	int i, j;
 
-	left = effect->u.rumble.strong_magnitude;
-	right = effect->u.rumble.weak_magnitude;
-
-	dbg_hid("called with 0x%04x 0x%04x", left, right);
-
-	left = left * 0xff / 0xffff;
-	right = right * 0xff / 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 * 0xff / 0xffff;
+		right = right * 0xff / 0xffff;
+		break;
+	case MLNX_STOP_RUMBLE:
+		left = 0;
+		right = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	for (i = 0; i < report->maxfield; i++) {
 		for (j = 0; j < report->field[i]->report_count; j++) {
@@ -107,7 +121,7 @@ static int axff_init(struct hid_device *hid)
 
 	set_bit(FF_RUMBLE, dev->ffbit);
 
-	error = input_ff_create_memless(dev, axff, axff_play);
+	error = input_ff_create_mlnx(dev, axff, axff_play, FF_UPDATE_RATE);
 	if (error)
 		goto err_free_mem;
 
-- 
1.9.2

^ permalink raw reply related

* [PATCH v3 08/24] hid: Port hid-emsff to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

Port hid-emsff to ff-memless-next

Signed-off-by: Michal Malý <madcatxster@devoid-pointer.net>
---
 drivers/hid/Kconfig     |  2 +-
 drivers/hid/hid-emsff.c | 38 ++++++++++++++++++++++++++------------
 2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index e076627..a78b5d8 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -213,7 +213,7 @@ config DRAGONRISE_FF
 config HID_EMS_FF
 	tristate "EMS Production Inc. force feedback support"
 	depends on HID
-	select INPUT_FF_MEMLESS
+	select INPUT_FF_MEMLESS_NEXT
 	---help---
 	Say Y here if you want to enable force feedback support for devices by
 	EMS Production Ltd.
diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c
index d82d75b..c0cbe50 100644
--- a/drivers/hid/hid-emsff.c
+++ b/drivers/hid/hid-emsff.c
@@ -24,30 +24,44 @@
 #include <linux/hid.h>
 #include <linux/input.h>
 #include <linux/module.h>
+#include <linux/input/ff-memless-next.h>
 
 #include "hid-ids.h"
 
+#define FF_UPDATE_RATE 50
+
 struct emsff_device {
 	struct hid_report *report;
 };
 
 static int emsff_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 emsff_device *emsff = data;
+	const struct mlnx_rumble_force *rumble_force = &command->u.rumble_force;
 	int weak, strong;
 
-	weak = effect->u.rumble.weak_magnitude;
-	strong = effect->u.rumble.strong_magnitude;
-
-	dbg_hid("called with 0x%04x 0x%04x\n", strong, weak);
-
-	weak = weak * 0xff / 0xffff;
-	strong = strong * 0xff / 0xffff;
-
-	emsff->report->field[0]->value[1] = weak;
-	emsff->report->field[0]->value[2] = strong;
+	switch (command->cmd) {
+	case MLNX_START_RUMBLE:
+		weak = rumble_force->weak;
+		strong = rumble_force->strong;
+
+		dbg_hid("called with 0x%04x 0x%04x\n", strong, weak);
+
+		weak = weak * 0xff / 0xffff;
+		strong = strong * 0xff / 0xffff;
+
+		emsff->report->field[0]->value[1] = weak;
+		emsff->report->field[0]->value[2] = strong;
+		break;
+	case MLNX_STOP_RUMBLE:
+		weak = 0;
+		strong = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	dbg_hid("running with 0x%02x 0x%02x\n", strong, weak);
 	hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
@@ -88,7 +102,7 @@ static int emsff_init(struct hid_device *hid)
 
 	set_bit(FF_RUMBLE, dev->ffbit);
 
-	error = input_ff_create_memless(dev, emsff, emsff_play);
+	error = input_ff_create_mlnx(dev, emsff, emsff_play, FF_UPDATE_RATE);
 	if (error) {
 		kfree(emsff);
 		return error;
-- 
1.9.2

^ permalink raw reply related

* [PATCH v3 09/24] hid: Port hid-dr to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 a78b5d8..1d4180c 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -205,7 +205,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.2

^ permalink raw reply related

* [PATCH v3 11/24] hid: Port hid-holtekff to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 4c59a88..1749a4a 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -256,7 +256,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.2

^ permalink raw reply related

* [PATCH v3 12/24] hid: Port hid-lgff to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 | 70 +++++++++++++++++++++++++++++++++++---------------
 2 files changed, 51 insertions(+), 21 deletions(-)

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 1749a4a..c4b0cbb 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -365,7 +365,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..40ad68a 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,11 +50,25 @@ 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
 };
 
 static const signed short ff_joystick_ac[] = {
 	FF_CONSTANT,
+	FF_RAMP,
+	FF_PERIODIC,
+	FF_SQUARE,
+	FF_TRIANGLE,
+	FF_SINE,
+	FF_SAW_UP,
+	FF_SAW_DOWN,
 	FF_AUTOCENTER,
 	-1
 };
@@ -66,45 +83,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 = 0x80 - (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] = 0x80;
+		report->field[0]->value[3] = 0x80;
+		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 +178,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.2

^ permalink raw reply related

* [PATCH v3 13/24] hid: Port hid-lg3ff to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 | 60 +++++++++++++++++++++++++++++++------------------
 2 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index c4b0cbb..eb0c7f1 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -391,7 +391,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..c49b374 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;
-
-/*
- * 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);
+	/* send command byte */
+	report->field[0]->value[0] = 0x51;
 
-		hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+	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 = 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;
+		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.2

^ permalink raw reply related

* [PATCH v3 14/24] hid: Port hid-pl to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 eb0c7f1..42904e4 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -509,7 +509,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.2

^ permalink raw reply related

* [PATCH v3 15/24] hid: Port hid-sjoy to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 42904e4..9260d14 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -692,7 +692,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.2

^ permalink raw reply related

* [PATCH v3 16/24] hid: Port hid-sony to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 9260d14..e97c382 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -634,7 +634,7 @@ config HID_SONY
 config SONY_FF
 	bool "Sony PS2/3/4 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/4 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 908de27..95bb2e1 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -34,6 +34,7 @@
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/input/mt.h>
+#include <linux/input/ff-memless-next.h>
 
 #include "hid-ids.h"
 
@@ -53,6 +54,7 @@
 #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)
 #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)
 
+#define FF_UPDATE_RATE 50
 #define MAX_LEDS 4
 
 static const u8 sixaxis_rdesc_fixup[] = {
@@ -1308,16 +1310,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;
@@ -1330,7 +1341,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
@@ -1762,6 +1773,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.2

^ permalink raw reply related

* [PATCH v3 17/24] hid: Port hid-tmff to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 e97c382..17ed5cf 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -730,7 +730,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.2

^ permalink raw reply related

* [PATCH v3 18/24] hid: Port hid-wiimote-modules to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 17ed5cf..23d9776 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -749,7 +749,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.2

^ permalink raw reply related

* [PATCH v3 19/24] hid: Port hid-zpff to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 23d9776..97d2d8f 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -786,7 +786,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.2

^ permalink raw reply related

* [PATCH v3 20/24] input: Port gamecon to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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.2

^ permalink raw reply related

* [PATCH v3 21/24] input: Port xpad to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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.2

^ permalink raw reply related

* [PATCH v3 22/24] hid: Port hid-lg2ff to ff-memless-next
From: Michal Malý @ 2014-04-26 11:57 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: dmitry.torokhov, jkosina, elias.vds, anssi.hannula, simon,
	Michal Malý
In-Reply-To: <1398513696-12626-1-git-send-email-madcatxster@devoid-pointer.net>

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 97d2d8f..5e70519 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -381,7 +381,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.2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox