summaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2009-11-30 09:04:02 +0100
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-11-30 09:05:20 +0100
commit6ee88d713fb75ab191515f66edffa4e866386565 (patch)
treee1d5230d0d6ce85f4194e2744c5318e63fa2f190 /drivers/input
parentInput: keyboard - add locking around event handling (diff)
downloadlinux-6ee88d713fb75ab191515f66edffa4e866386565.tar.xz
linux-6ee88d713fb75ab191515f66edffa4e866386565.zip
Input: gpio_keys - scan gpio state at probe and resume time
We need to read and report gpio state when we bind the driver to the device and upon resume so that userspace has correct state of the switches (and keys but they are less important since, even if they are happened to be pressed, we'd expect them to be released fairly soon). Signed-off-by: Daniel Mack <daniel@caiaq.de> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/gpio_keys.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 8941a8ba89bf..1aff3b76effd 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -37,10 +37,8 @@ struct gpio_keys_drvdata {
struct gpio_button_data data[0];
};
-static void gpio_keys_report_event(struct work_struct *work)
+static void gpio_keys_report_event(struct gpio_button_data *bdata)
{
- struct gpio_button_data *bdata =
- container_of(work, struct gpio_button_data, work);
struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY;
@@ -50,6 +48,14 @@ static void gpio_keys_report_event(struct work_struct *work)
input_sync(input);
}
+static void gpio_keys_work_func(struct work_struct *work)
+{
+ struct gpio_button_data *bdata =
+ container_of(work, struct gpio_button_data, work);
+
+ gpio_keys_report_event(bdata);
+}
+
static void gpio_keys_timer(unsigned long _data)
{
struct gpio_button_data *data = (struct gpio_button_data *)_data;
@@ -81,7 +87,7 @@ static int __devinit gpio_keys_setup_key(struct device *dev,
int irq, error;
setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata);
- INIT_WORK(&bdata->work, gpio_keys_report_event);
+ INIT_WORK(&bdata->work, gpio_keys_work_func);
error = gpio_request(button->gpio, desc);
if (error < 0) {
@@ -185,6 +191,11 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
goto fail2;
}
+ /* get current state of buttons */
+ for (i = 0; i < pdata->nbuttons; i++)
+ gpio_keys_report_event(&ddata->data[i]);
+ input_sync(input);
+
device_init_wakeup(&pdev->dev, wakeup);
return 0;
@@ -253,18 +264,21 @@ static int gpio_keys_suspend(struct device *dev)
static int gpio_keys_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
+ struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
int i;
- if (device_may_wakeup(&pdev->dev)) {
- for (i = 0; i < pdata->nbuttons; i++) {
- struct gpio_keys_button *button = &pdata->buttons[i];
- if (button->wakeup) {
- int irq = gpio_to_irq(button->gpio);
- disable_irq_wake(irq);
- }
+ for (i = 0; i < pdata->nbuttons; i++) {
+
+ struct gpio_keys_button *button = &pdata->buttons[i];
+ if (button->wakeup && device_may_wakeup(&pdev->dev)) {
+ int irq = gpio_to_irq(button->gpio);
+ disable_irq_wake(irq);
}
+
+ gpio_keys_report_event(&ddata->data[i]);
}
+ input_sync(ddata->input);
return 0;
}