From patchwork Mon Nov 9 13:03:03 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: samu.p.onkalo@nokia.com X-Patchwork-Id: 58758 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nA9D3NxY024908 for ; Mon, 9 Nov 2009 13:03:23 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755242AbZKINDL (ORCPT ); Mon, 9 Nov 2009 08:03:11 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754920AbZKINDK (ORCPT ); Mon, 9 Nov 2009 08:03:10 -0500 Received: from smtp.nokia.com ([192.100.105.134]:48074 "EHLO mgw-mx09.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754664AbZKINDJ (ORCPT ); Mon, 9 Nov 2009 08:03:09 -0500 Received: from vaebh106.NOE.Nokia.com (vaebh106.europe.nokia.com [10.160.244.32]) by mgw-mx09.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id nA9D32hT006294; Mon, 9 Nov 2009 07:03:13 -0600 Received: from vaebh104.NOE.Nokia.com ([10.160.244.30]) by vaebh106.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); Mon, 9 Nov 2009 15:03:07 +0200 Received: from mgw-sa01.ext.nokia.com ([147.243.1.47]) by vaebh104.NOE.Nokia.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959); Mon, 9 Nov 2009 15:03:07 +0200 Received: from localhost.localdomain (4fid08082.ntc.nokia.com [172.22.144.188]) by mgw-sa01.ext.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id nA9D34eJ018951; Mon, 9 Nov 2009 15:03:06 +0200 From: Samu Onkalo To: dmitry.torokhov@gmail.com Cc: linux-input@vger.kernel.org, Samu Onkalo Subject: [PATCH 1/1] Input polldev: Sysfs interface for setting of polling interval Date: Mon, 9 Nov 2009 15:03:03 +0200 Message-Id: <1257771783-31210-2-git-send-email-samu.p.onkalo@nokia.com> X-Mailer: git-send-email 1.5.6.3 In-Reply-To: <1257771783-31210-1-git-send-email-samu.p.onkalo@nokia.com> References: <1257771783-31210-1-git-send-email-samu.p.onkalo@nokia.com> X-OriginalArrivalTime: 09 Nov 2009 13:03:07.0497 (UTC) FILETIME=[FB444D90:01CA613C] X-Nokia-AV: Clean Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 910220c..5d7fffd 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c @@ -46,10 +46,12 @@ static int input_polldev_start_workqueue(void) return retval; } -static void input_polldev_stop_workqueue(void) +static void input_polldev_stop_workqueue(struct input_polled_dev *dev) { mutex_lock(&polldev_mutex); + cancel_delayed_work_sync(&dev->work); + if (!--polldev_users) destroy_workqueue(polldev_wq); @@ -83,6 +85,8 @@ static int input_open_polled_device(struct input_dev *input) if (dev->open) dev->open(dev); + dev->is_opened = 1; + queue_delayed_work(polldev_wq, &dev->work, msecs_to_jiffies(dev->poll_interval)); @@ -93,13 +97,72 @@ static void input_close_polled_device(struct input_dev *input) { struct input_polled_dev *dev = input_get_drvdata(input); - cancel_delayed_work_sync(&dev->work); - input_polldev_stop_workqueue(); + dev->is_opened = 0; + input_polldev_stop_workqueue(dev); if (dev->close) dev->close(dev); } +/* SYSFS interface */ + +static ssize_t input_polldev_get_interval(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct input_polled_dev *polldev = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", polldev->poll_interval); +} + +static ssize_t input_polldev_set_interval(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) +{ + struct input_polled_dev *polldev = dev_get_drvdata(dev); + unsigned long delay; + unsigned long interval; + + if (strict_strtoul(buf, 0, &interval)) + return -EINVAL; + + if (interval < polldev->poll_interval_min) + return -EINVAL; + + if (interval > polldev->poll_interval_max) + return -EINVAL; + + mutex_lock(&polldev_mutex); + + polldev->poll_interval = interval; + + if (polldev->is_opened) { + if (polldev->poll_interval > 0) { + delay = msecs_to_jiffies(polldev->poll_interval); + if (delay >= HZ) + delay = round_jiffies_relative(delay); + + queue_delayed_work(polldev_wq, &polldev->work, delay); + } else { + cancel_delayed_work_sync(&polldev->work); + } + } + mutex_unlock(&polldev_mutex); + + return count; +} + +static DEVICE_ATTR(interval, S_IRUGO | S_IWUSR, input_polldev_get_interval, + input_polldev_set_interval); + +static struct attribute *sysfs_attrs[] = { + &dev_attr_interval.attr, + NULL +}; + +static struct attribute_group input_polldev_attribute_group = { + .attrs = sysfs_attrs +}; + /** * input_allocate_polled_device - allocated memory polled device * @@ -153,15 +216,27 @@ EXPORT_SYMBOL(input_free_polled_device); int input_register_polled_device(struct input_polled_dev *dev) { struct input_dev *input = dev->input; + int error; input_set_drvdata(input, dev); INIT_DELAYED_WORK(&dev->work, input_polled_device_work); if (!dev->poll_interval) dev->poll_interval = 500; + if (!dev->poll_interval_max) + dev->poll_interval_max = dev->poll_interval; input->open = input_open_polled_device; input->close = input_close_polled_device; - return input_register_device(input); + error = input_register_device(input); + if (error < 0) + goto fail; + + error = sysfs_create_group(&input->dev.kobj, + &input_polldev_attribute_group); + if (error < 0) + input_unregister_device(input); +fail: + return error; } EXPORT_SYMBOL(input_register_polled_device); @@ -177,6 +252,9 @@ EXPORT_SYMBOL(input_register_polled_device); */ void input_unregister_polled_device(struct input_polled_dev *dev) { + sysfs_remove_group(&dev->input->dev.kobj, + &input_polldev_attribute_group); + input_unregister_device(dev->input); dev->input = NULL; } diff --git a/include/linux/input-polldev.h b/include/linux/input-polldev.h index 5c0ec68..f2b1e03 100644 --- a/include/linux/input-polldev.h +++ b/include/linux/input-polldev.h @@ -36,6 +36,9 @@ struct input_polled_dev { void (*close)(struct input_polled_dev *dev); void (*poll)(struct input_polled_dev *dev); unsigned int poll_interval; /* msec */ + unsigned int poll_interval_max; /* msec */ + unsigned int poll_interval_min; /* msec */ + int is_opened; struct input_dev *input; struct delayed_work work;