From: Dmitry Torokhov <dtor@insightbb.com>
To: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
Cc: linux-input@atrey.karlin.mff.cuni.cz
Subject: Re: [PATCH] Add Cobalt button interface driver support
Date: Wed, 25 Apr 2007 01:34:33 -0400 [thread overview]
Message-ID: <200704250134.33610.dtor@insightbb.com> (raw)
In-Reply-To: <200704050502.l3552gss048910@mbox31.po.2iij.net>
[-- Attachment #1: Type: text/plain, Size: 606 bytes --]
Hi Yoichi,
On Thursday 05 April 2007 01:02, Yoichi Yuasa wrote:
> Hi Dmitry,
>
> On Wed, 4 Apr 2007 00:01:41 -0400
> Dmitry Torokhov <dtor@insightbb.com> wrote:
>
> > Hi Yoichi,
> >
> > Could you please try the patch below? It moves platform device creation
> > code into cobalt arch code to belletr follow driver model.
>
> It works fine.
>
Coudl you please try couple more patches, please? I wrote a generic
stub for polled (as opposed to interrupt-driven) input devices and
converting existing drivers to use it. Cobalt buttons seem to be
a good candidate...
Thank you in advance.
--
Dmitry
[-- Attachment #2: polled-button.patch --]
[-- Type: text/x-diff, Size: 7867 bytes --]
Subject: XXX
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/misc/Kconfig | 11 ++
drivers/input/misc/Makefile | 1
drivers/input/misc/input-polldev.c | 171 +++++++++++++++++++++++++++++++++++++
include/linux/input-polldev.h | 46 +++++++++
4 files changed, 229 insertions(+)
Index: work/drivers/input/misc/Kconfig
===================================================================
--- work.orig/drivers/input/misc/Kconfig
+++ work/drivers/input/misc/Kconfig
@@ -90,6 +90,17 @@ config INPUT_UINPUT
To compile this driver as a module, choose M here: the
module will be called uinput.
+config INPUT_POLLDEV
+ tristate "Polled input device skeleton"
+ help
+ Say Y here if you are using a driver for an input
+ device that periodically polls hardware state. This
+ option is only useful for out-of-tree drivers since
+ in-tree drivers select it automatically.
+
+ To compile this driver as a module, choose M here: the
+ module will be called input-polldev.
+
config HP_SDC_RTC
tristate "HP SDC Real Time Clock"
depends on GSC || HP300
Index: work/drivers/input/misc/Makefile
===================================================================
--- work.orig/drivers/input/misc/Makefile
+++ work/drivers/input/misc/Makefile
@@ -4,6 +4,7 @@
# Each configuration option enables a list of files.
+obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
Index: work/drivers/input/misc/input-polldev.c
===================================================================
--- /dev/null
+++ work/drivers/input/misc/input-polldev.c
@@ -0,0 +1,171 @@
+/*
+ * Generic implementation of a polled input device
+
+ * Copyright (c) 2007 Dmitry Torokhov
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/input-polldev.h>
+
+static DEFINE_MUTEX(polldev_mutex);
+static int polldev_users;
+static struct workqueue_struct *polldev_wq;
+
+static int input_polldev_start_workqueue(void)
+{
+ int retval;
+
+ retval = mutex_lock_interruptible(&polldev_mutex);
+ if (retval)
+ return retval;
+
+ if (!polldev_users) {
+ polldev_wq = create_singlethread_workqueue("ipolldevd");
+ if (!polldev_wq) {
+ printk(KERN_ERR "input-polldev: failed to create "
+ "ipolldevd workqueue\n");
+ retval = -ENOMEM;
+ goto out;
+ }
+ }
+
+ polldev_users++;
+
+ out:
+ mutex_unlock(&polldev_mutex);
+ return retval;
+}
+
+static void input_polldev_stop_workqueue(void)
+{
+ mutex_lock(&polldev_mutex);
+
+ if (!--polldev_users)
+ destroy_workqueue(polldev_wq);
+
+ mutex_unlock(&polldev_mutex);
+}
+
+static void input_polled_device_work(struct work_struct *work)
+{
+ struct input_polled_dev *dev =
+ container_of(work, struct input_polled_dev, work.work);
+
+ dev->poll(dev);
+ queue_delayed_work(polldev_wq, &dev->work,
+ msecs_to_jiffies(dev->poll_interval));
+}
+
+static int input_open_polled_device(struct input_dev *input)
+{
+ struct input_polled_dev *dev = input->private;
+ int error;
+
+ error = input_polldev_start_workqueue();
+ if (error)
+ return error;
+
+ if (dev->flush)
+ dev->flush(dev);
+
+ queue_delayed_work(polldev_wq, &dev->work,
+ msecs_to_jiffies(dev->poll_interval));
+
+ return 0;
+}
+
+static void input_close_polled_device(struct input_dev *input)
+{
+ struct input_polled_dev *dev = input->private;
+
+ cancel_rearming_delayed_workqueue(polldev_wq, &dev->work);
+ input_polldev_stop_workqueue();
+}
+
+/**
+ * input_allocate_polled_device - allocated memory polled device
+ *
+ * The function allocates memory for a polled device and also
+ * for an input device associated with this polled device.
+ */
+struct input_polled_dev *input_allocate_polled_device(void)
+{
+ struct input_polled_dev *dev;
+
+ dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ dev->input = input_allocate_device();
+ if (!dev->input) {
+ kfree(dev);
+ return NULL;
+ }
+
+ return dev;
+}
+EXPORT_SYMBOL(input_allocate_polled_device);
+
+/**
+ * input_free_polled_device - free memory allocated for polled device
+ * @dev: device to free
+ *
+ * The function frees memory allocated for pollign device and drops
+ * reference to the associated input device (if present).
+ */
+void input_free_polled_device(struct input_polled_dev *dev)
+{
+ if (dev) {
+ input_free_device(dev->input);
+ kfree(dev);
+ }
+}
+EXPORT_SYMBOL(input_free_polled_device);
+
+/**
+ * input_register_polled_device - register polled device
+ * @dev: device to register
+ *
+ * The function registers previously initialized polled input device
+ * with input layer. The device should be allocated with call to
+ * input_allocate_polled_device(). Callers should also set up poll()
+ * method and set up capabilities (id, name, phys, bits) of the
+ * corresponing input_dev structure.
+ */
+int input_register_polled_device(struct input_polled_dev *dev)
+{
+ struct input_dev *input = dev->input;
+
+ INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
+ if (!dev->poll_interval)
+ dev->poll_interval = 500;
+ input->private = dev;
+ input->open = input_open_polled_device;
+ input->close = input_close_polled_device;
+
+ return input_register_device(input);
+}
+EXPORT_SYMBOL(input_register_polled_device);
+
+/**
+ * input_unregister_polled_device - unregister polled device
+ * @dev: device to unregister
+ *
+ * The function unregisters previously registered polled input
+ * device from input layer. Polling is stopped and device is
+ * ready to be freed with call to input_free_polled_device().
+ * Callers should not attempt to access dev->input pointer
+ * after calling this function.
+ */
+void input_unregister_polled_device(struct input_polled_dev *dev)
+{
+ input_unregister_device(dev->input);
+ dev->input = NULL;
+}
+EXPORT_SYMBOL(input_unregister_polled_device);
+
Index: work/include/linux/input-polldev.h
===================================================================
--- /dev/null
+++ work/include/linux/input-polldev.h
@@ -0,0 +1,46 @@
+#ifndef _INPUT_POLLDEV_H
+#define _INPUT_POLLDEV_H
+
+/*
+ * Copyright (c) 2007 Dmitry Torokhov
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/input.h>
+#include <linux/workqueue.h>
+
+/**
+ * struct input_polled_dev - simple polled input device
+ * @private: private driver data
+ * @flush: driver-supplied method that flushes device's state upon
+ * opening (optional)
+ * @poll: driver-supplied method that polls the device and posts
+ * input events (mandatory).
+ * @poll_interval: specifies how often the poll() method shoudl be called.
+ * @input: input device structire associated with the polled device.
+ * Must be properly initialized by the driver (id, name, phys, bits).
+ *
+ * Polled input device provides a skeleton for supporting simple input
+ * devices that do not raise interrupts but have to be periodically
+ * scanned to detect changes in their state.
+ */
+struct input_polled_dev {
+ void *private;
+
+ void (*flush)(struct input_polled_dev *dev);
+ void (*poll)(struct input_polled_dev *dev);
+ unsigned int poll_interval; /* msec */
+
+ struct input_dev *input;
+ struct delayed_work work;
+};
+
+struct input_polled_dev *input_allocate_polled_device(void);
+void input_free_polled_device(struct input_polled_dev *dev);
+int input_register_polled_device(struct input_polled_dev *dev);
+void input_unregister_polled_device(struct input_polled_dev *dev);
+
+#endif
[-- Attachment #3: cobalt-to-polldev.patch --]
[-- Type: text/x-diff, Size: 4866 bytes --]
Subject: XXX
Input: cobalt_btns - convert to use polldev library
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
drivers/input/misc/Kconfig | 1
drivers/input/misc/cobalt_btns.c | 59 ++++++++++++++-------------------------
2 files changed, 23 insertions(+), 37 deletions(-)
Index: work/drivers/input/misc/cobalt_btns.c
===================================================================
--- work.orig/drivers/input/misc/cobalt_btns.c
+++ work/drivers/input/misc/cobalt_btns.c
@@ -18,19 +18,17 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/init.h>
-#include <linux/input.h>
+#include <linux/input-polldev.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
#define BUTTONS_POLL_INTERVAL 30 /* msec */
#define BUTTONS_COUNT_THRESHOLD 3
#define BUTTONS_STATUS_MASK 0xfe000000
struct buttons_dev {
- struct input_dev *input;
+ struct input_polled_dev *poll_dev;
void __iomem *reg;
};
@@ -50,16 +48,14 @@ static struct buttons_map buttons_map[]
{ 0x80000000, KEY_SELECT, },
};
-static struct timer_list buttons_timer;
-
-static void handle_buttons(unsigned long data)
+static void handle_buttons(struct input_polled_dev *dev)
{
struct buttons_map *button = buttons_map;
- struct buttons_dev *bdev;
+ struct buttons_dev *bdev = dev->private;
+ struct input_dev *input = dev->input;
uint32_t status;
int i;
- bdev = (struct buttons_dev *)data;
status = readl(bdev->reg);
status = ~status & BUTTONS_STATUS_MASK;
@@ -68,55 +64,45 @@ static void handle_buttons(unsigned long
button->count++;
} else {
if (button->count >= BUTTONS_COUNT_THRESHOLD) {
- input_report_key(bdev->input, button->keycode, 0);
- input_sync(bdev->input);
+ input_report_key(input, button->keycode, 0);
+ input_sync(input);
}
button->count = 0;
}
if (button->count == BUTTONS_COUNT_THRESHOLD) {
- input_report_key(bdev->input, button->keycode, 1);
- input_sync(bdev->input);
+ input_report_key(input, button->keycode, 1);
+ input_sync(input);
}
button++;
}
-
- mod_timer(&buttons_timer, jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL));
-}
-
-static int cobalt_buttons_open(struct input_dev *dev)
-{
- mod_timer(&buttons_timer, jiffies + msecs_to_jiffies(BUTTONS_POLL_INTERVAL));
-
- return 0;
-}
-
-static void cobalt_buttons_close(struct input_dev *dev)
-{
- del_timer_sync(&buttons_timer);
}
static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
{
struct buttons_dev *bdev;
+ struct input_polled_dev *poll_dev;
struct input_dev *input;
struct resource *res;
int error, i;
bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
- input = input_allocate_device();
- if (!bdev || !input) {
+ poll_dev = input_allocate_polled_device();
+ if (!bdev || !poll_dev) {
error = -ENOMEM;
goto err_free_mem;
}
+ poll_dev->private = bdev;
+ poll_dev->poll = handle_buttons;
+ poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
+
+ input = poll_dev->input;
input->name = "Cobalt buttons";
input->phys = "cobalt/input0";
input->id.bustype = BUS_HOST;
input->cdev.dev = &pdev->dev;
- input->open = cobalt_buttons_open;
- input->close = cobalt_buttons_close;
input->evbit[0] = BIT(EV_KEY);
for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
@@ -130,13 +116,11 @@ static int __devinit cobalt_buttons_prob
goto err_free_mem;
}
- bdev->input = input;
+ bdev->poll_dev = poll_dev;
bdev->reg = ioremap(res->start, res->end - res->start + 1);
dev_set_drvdata(&pdev->dev, bdev);
- setup_timer(&buttons_timer, handle_buttons, (unsigned long)bdev);
-
- error = input_register_device(input);
+ error = input_register_polled_device(poll_dev);
if (error)
goto err_iounmap;
@@ -145,7 +129,7 @@ static int __devinit cobalt_buttons_prob
err_iounmap:
iounmap(bdev->reg);
err_free_mem:
- input_free_device(input);
+ input_free_polled_device(poll_dev);
kfree(bdev);
dev_set_drvdata(&pdev->dev, NULL);
return error;
@@ -156,7 +140,8 @@ static int __devexit cobalt_buttons_remo
struct device *dev = &pdev->dev;
struct buttons_dev *bdev = dev_get_drvdata(dev);
- input_unregister_device(bdev->input);
+ input_unregister_polled_device(bdev->poll_dev);
+ input_free_polled_device(bdev->poll_dev);
iounmap(bdev->reg);
kfree(bdev);
dev_set_drvdata(dev, NULL);
Index: work/drivers/input/misc/Kconfig
===================================================================
--- work.orig/drivers/input/misc/Kconfig
+++ work/drivers/input/misc/Kconfig
@@ -43,6 +43,7 @@ config INPUT_M68K_BEEP
config INPUT_COBALT_BTNS
tristate "Cobalt button interface"
depends on MIPS_COBALT
+ select INPUT_POLLDEV
help
Say Y here if you want to support MIPS Cobalt button interface.
next prev parent reply other threads:[~2007-04-25 5:34 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-02-16 3:36 [PATCH] Add Cobalt button interface driver support Yoichi Yuasa
2007-02-16 4:09 ` Dmitry Torokhov
2007-02-16 8:15 ` Yoichi Yuasa
2007-02-16 15:15 ` Dmitry Torokhov
2007-02-16 16:22 ` Yoichi Yuasa
2007-04-04 4:01 ` Dmitry Torokhov
2007-04-05 5:02 ` Yoichi Yuasa
2007-04-25 5:34 ` Dmitry Torokhov [this message]
2007-04-26 6:40 ` Yoichi Yuasa
2007-04-26 12:29 ` Dmitry Torokhov
2007-09-18 4:59 ` Dmitry Torokhov
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=200704250134.33610.dtor@insightbb.com \
--to=dtor@insightbb.com \
--cc=linux-input@atrey.karlin.mff.cuni.cz \
--cc=yoichi_yuasa@tripeaks.co.jp \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.