linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: <paul.chavent@fnac.net>
To: michael.hennerich@analog.com
Cc: dmitry.torokhov@gmail.com,
	device-driver-devel@blackfin.uclinux.org,
	linux-input@vger.kernel.org
Subject: input_polling_devices design question + adxl34x polling mode patch
Date: Mon, 11 Apr 2011 18:21:02 +0200 (CEST)	[thread overview]
Message-ID: <17876647.33591302538862973.JavaMail.www@wsfrf1114> (raw)

[-- Attachment #1: Type: text/plain, Size: 972 bytes --]

Hi.

I have  a board with an adxl34x (an accelerometer) on a two wire bus. Its interrupt line aren't routed.

So i would like to use the driver in polling mode.

I submit this patch as a beta version of my work.

I tried to reuse the input_polling structure but I'm facing some problems.

The driver has a "rate" attribute that i would like to control when i setup the "interval" attribute of the input_pollling.

And vice versa, when i setup the "interval" attribute i would like to setup the "rate".

So my questions :
 - Is it possible to reimplement a workqueue for this driver only ? As it seems to have been done yet in other drivers, i wonder if it's acceptable, or if we should avoid this practice.
 - I think it would be complicated to have hooks in input and input_polling for calling each other. I wonder if i haven't any design problem.

I would need an advice in order to cleaning this patch please.

Thank for your help.

Paul.



[-- Attachment #2: 0001-Polling-option-for-adxl34x-input-driver.patch --]
[-- Type: application/octet-stream, Size: 6773 bytes --]

From a03ffc414bff628317d191fde4a9e8fe8b6e669c Mon Sep 17 00:00:00 2001
From: Paul Chavent <paul.chavent@fnac.net>
Date: Mon, 11 Apr 2011 18:01:33 +0200
Subject: [PATCH] Polling option for adxl34x input driver.

---
 drivers/input/misc/adxl34x.c |  138 +++++++++++++++++++++++++++++++++++++-----
 1 files changed, 122 insertions(+), 16 deletions(-)

diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c
index 144ddbd..88b99f4 100644
--- a/drivers/input/misc/adxl34x.c
+++ b/drivers/input/misc/adxl34x.c
@@ -11,6 +11,9 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/input.h>
+#if defined(CONFIG_INPUT_POLLDEV)
+#include <linux/input-polldev.h>
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
@@ -190,6 +193,9 @@ struct axis_triple {
 struct adxl34x {
 	struct device *dev;
 	struct input_dev *input;
+#if defined(CONFIG_INPUT_POLLDEV)
+	struct input_polled_dev *input_polled;
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
 	struct mutex mutex;	/* reentrant protection for struct */
 	struct adxl34x_platform_data pdata;
 	struct axis_triple swcal;
@@ -688,27 +694,75 @@ static void adxl34x_input_close(struct input_dev *input)
 	mutex_unlock(&ac->mutex);
 }
 
+#if defined(CONFIG_INPUT_POLLDEV)
+
+static void adxl34x_input_polled_open(struct input_polled_dev *dev)
+{
+	adxl34x_input_open(dev->input);
+}
+
+static void adxl34x_input_polled_close(struct input_polled_dev *dev)
+{
+	adxl34x_input_close(dev->input);
+}
+
+static void adxl34x_input_polled_poll(struct input_polled_dev *dev)
+{
+	struct adxl34x *ac = input_get_drvdata(dev->input);
+
+	adxl34x_irq(ac->irq, ac);
+}
+
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
+
 struct adxl34x *adxl34x_probe(struct device *dev, int irq,
 			      bool fifo_delay_default,
 			      const struct adxl34x_bus_ops *bops)
 {
 	struct adxl34x *ac;
 	struct input_dev *input_dev;
+#if defined(CONFIG_INPUT_POLLDEV)
+	struct input_polled_dev *input_polled_dev;
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
 	const struct adxl34x_platform_data *pdata;
 	int err, range, i;
 	unsigned char revid;
 
-	if (!irq) {
-		dev_err(dev, "no IRQ?\n");
-		err = -ENODEV;
+
+	ac = kzalloc(sizeof(*ac), GFP_KERNEL);
+	if (!ac) {
+		err = -ENOMEM;
 		goto err_out;
 	}
 
-	ac = kzalloc(sizeof(*ac), GFP_KERNEL);
+	ac->irq = irq;
+
+	if (ac->irq) {
+#if defined(CONFIG_INPUT_POLLDEV)
+		input_polled_dev = 0;
+		ac->input_polled = input_polled_dev;
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
+
 	input_dev = input_allocate_device();
-	if (!ac || !input_dev) {
+		if (!input_dev) {
 		err = -ENOMEM;
-		goto err_free_mem;
+			goto err_free_ac;
+		}
+	} else {
+#if defined(CONFIG_INPUT_POLLDEV)
+		input_polled_dev = input_allocate_polled_device();
+		if (!input_polled_dev) {
+			err = -ENOMEM;
+			goto err_free_ac;
+		}
+		ac->input_polled = input_polled_dev;
+
+		input_dev = input_polled_dev->input;
+#else
+		dev_err(dev, "no IRQ? (perhaps you need to set CONFIG_INPUT_POLLDEV=y)\n");
+		err = -ENODEV;
+		goto err_free_ac;
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
 	}
 
 	ac->fifo_delay = fifo_delay_default;
@@ -725,7 +779,6 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
 
 	ac->input = input_dev;
 	ac->dev = dev;
-	ac->irq = irq;
 	ac->bops = bops;
 
 	mutex_init(&ac->mutex);
@@ -743,7 +796,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
 	default:
 		dev_err(dev, "Failed to probe %s\n", input_dev->name);
 		err = -ENODEV;
-		goto err_free_mem;
+		goto err_free_dev;
 	}
 
 	snprintf(ac->phys, sizeof(ac->phys), "%s/input0", dev_name(dev));
@@ -752,8 +805,15 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
 	input_dev->dev.parent = dev;
 	input_dev->id.product = ac->model;
 	input_dev->id.bustype = bops->bustype;
+	if (ac->irq) {
 	input_dev->open = adxl34x_input_open;
 	input_dev->close = adxl34x_input_close;
+	} else {
+#if defined(CONFIG_INPUT_POLLDEV)
+		input_polled_dev->open = adxl34x_input_polled_open;
+		input_polled_dev->close = adxl34x_input_polled_close;
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
+	}
 
 	input_set_drvdata(input_dev, ac);
 
@@ -810,21 +870,44 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
 
 	ac->bops->write(dev, POWER_CTL, 0);
 
+	if (ac->irq) {
 	err = request_threaded_irq(ac->irq, NULL, adxl34x_irq,
 				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 				   dev_name(dev), ac);
+
 	if (err) {
 		dev_err(dev, "irq %d busy?\n", ac->irq);
-		goto err_free_mem;
+			goto err_free_dev;
 	}
 
-	err = sysfs_create_group(&dev->kobj, &adxl34x_attr_group);
+		err = input_register_device(input_dev);
 	if (err)
 		goto err_free_irq;
 
-	err = input_register_device(input_dev);
+		err = sysfs_create_group(&dev->kobj, &adxl34x_attr_group);
+		if (err)
+			goto err_unregister_dev;
+	} else {
+#if defined(CONFIG_INPUT_POLLDEV)
+		input_polled_dev->poll = adxl34x_input_polled_poll;
+
+		err = input_register_polled_device(input_polled_dev);
+		if (err)
+			goto err_free_dev;
+
+#if 0
+		err = sysfs_merge_group(&dev->kobj, &adxl34x_attr_group);
 	if (err)
-		goto err_remove_attr;
+			goto err_unregister_dev;
+#else
+#warning "FIXME : test with > 2.6.36"
+		err = sysfs_create_group(&dev->kobj, &adxl34x_attr_group);
+		if (err)
+			goto err_unregister_dev;
+#endif
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
+	}
+
 
 	AC_WRITE(ac, THRESH_TAP, pdata->tap_threshold);
 	AC_WRITE(ac, OFSX, pdata->x_axis_offset);
@@ -885,12 +968,27 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
 
 	return ac;
 
- err_remove_attr:
-	sysfs_remove_group(&dev->kobj, &adxl34x_attr_group);
+ err_unregister_dev:
+	if (ac->irq) {
+		input_unregister_device(input_dev);
+	} else {
+#if defined(CONFIG_INPUT_POLLDEV)
+		input_unregister_polled_device(input_polled_dev);
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
+	}
  err_free_irq:
+	if (ac->irq) {
 	free_irq(ac->irq, ac);
- err_free_mem:
+	}
+ err_free_dev:
+	if (ac->irq) {
 	input_free_device(input_dev);
+	} else {
+#if defined(CONFIG_INPUT_POLLDEV)
+		input_free_polled_device(input_polled_dev);
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
+	}
+ err_free_ac:
 	kfree(ac);
  err_out:
 	return ERR_PTR(err);
@@ -899,9 +997,17 @@ EXPORT_SYMBOL_GPL(adxl34x_probe);
 
 int adxl34x_remove(struct adxl34x *ac)
 {
+	if (ac->irq) {
 	sysfs_remove_group(&ac->dev->kobj, &adxl34x_attr_group);
-	free_irq(ac->irq, ac);
 	input_unregister_device(ac->input);
+		free_irq(ac->irq, ac);
+		input_free_device(ac->input);
+	} else {
+#if defined(CONFIG_INPUT_POLLDEV)
+		input_unregister_polled_device(ac->input_polled);
+		input_free_polled_device(ac->input_polled);
+#endif /* defined(CONFIG_INPUT_POLLDEV) */
+	}
 	dev_dbg(ac->dev, "unregistered accelerometer\n");
 	kfree(ac);
 
-- 
1.6.4


             reply	other threads:[~2011-04-11 16:24 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-11 16:21 paul.chavent [this message]
2011-04-12  6:23 ` input_polling_devices design question + adxl34x polling mode patch Dmitry Torokhov
  -- strict thread matches above, loose matches on Subject: below --
2011-04-12  7:22 paul.chavent
2011-04-12 16:57 paul.chavent
2011-04-13  8:39 ` Hennerich, Michael

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=17876647.33591302538862973.JavaMail.www@wsfrf1114 \
    --to=paul.chavent@fnac.net \
    --cc=device-driver-devel@blackfin.uclinux.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=michael.hennerich@analog.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).