Commit a33466e31213cd7c46696160d3db78680b58f6a3

Authored by Dmitry Baryshkov
Committed by Dmitry Torokhov
1 parent 885c316d77

Input: gpio-keys debouncing support

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

Showing 2 changed files with 70 additions and 20 deletions Side-by-side Diff

drivers/input/keyboard/gpio_keys.c
... ... @@ -26,23 +26,54 @@
26 26  
27 27 #include <asm/gpio.h>
28 28  
  29 +struct gpio_button_data {
  30 + struct gpio_keys_button *button;
  31 + struct input_dev *input;
  32 + struct timer_list timer;
  33 +};
  34 +
  35 +struct gpio_keys_drvdata {
  36 + struct input_dev *input;
  37 + struct gpio_button_data data[0];
  38 +};
  39 +
  40 +static void gpio_keys_report_event(struct gpio_keys_button *button,
  41 + struct input_dev *input)
  42 +{
  43 + unsigned int type = button->type ?: EV_KEY;
  44 + int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
  45 +
  46 + input_event(input, type, button->code, !!state);
  47 + input_sync(input);
  48 +}
  49 +
  50 +static void gpio_check_button(unsigned long _data)
  51 +{
  52 + struct gpio_button_data *data = (struct gpio_button_data *)_data;
  53 +
  54 + gpio_keys_report_event(data->button, data->input);
  55 +}
  56 +
29 57 static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
30 58 {
31   - int i;
32 59 struct platform_device *pdev = dev_id;
33 60 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
34   - struct input_dev *input = platform_get_drvdata(pdev);
  61 + struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
  62 + int i;
35 63  
36 64 for (i = 0; i < pdata->nbuttons; i++) {
37 65 struct gpio_keys_button *button = &pdata->buttons[i];
38   - int gpio = button->gpio;
39 66  
40   - if (irq == gpio_to_irq(gpio)) {
41   - unsigned int type = button->type ?: EV_KEY;
42   - int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low;
  67 + if (irq == gpio_to_irq(button->gpio)) {
  68 + struct gpio_button_data *bdata = &ddata->data[i];
43 69  
44   - input_event(input, type, button->code, !!state);
45   - input_sync(input);
  70 + if (button->debounce_interval)
  71 + mod_timer(&bdata->timer,
  72 + jiffies +
  73 + msecs_to_jiffies(button->debounce_interval));
  74 + else
  75 + gpio_keys_report_event(button, bdata->input);
  76 +
46 77 return IRQ_HANDLED;
47 78 }
48 79 }
49 80  
50 81  
51 82  
52 83  
... ... @@ -53,18 +84,22 @@
53 84 static int __devinit gpio_keys_probe(struct platform_device *pdev)
54 85 {
55 86 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
  87 + struct gpio_keys_drvdata *ddata;
56 88 struct input_dev *input;
57 89 int i, error;
58 90 int wakeup = 0;
59 91  
  92 + ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
  93 + pdata->nbuttons * sizeof(struct gpio_button_data),
  94 + GFP_KERNEL);
60 95 input = input_allocate_device();
61   - if (!input)
62   - return -ENOMEM;
  96 + if (!ddata || !input) {
  97 + error = -ENOMEM;
  98 + goto fail1;
  99 + }
63 100  
64   - platform_set_drvdata(pdev, input);
  101 + platform_set_drvdata(pdev, ddata);
65 102  
66   - input->evbit[0] = BIT_MASK(EV_KEY);
67   -
68 103 input->name = pdev->name;
69 104 input->phys = "gpio-keys/input0";
70 105 input->dev.parent = &pdev->dev;
71 106  
72 107  
73 108  
... ... @@ -74,16 +109,23 @@
74 109 input->id.product = 0x0001;
75 110 input->id.version = 0x0100;
76 111  
  112 + ddata->input = input;
  113 +
77 114 for (i = 0; i < pdata->nbuttons; i++) {
78 115 struct gpio_keys_button *button = &pdata->buttons[i];
  116 + struct gpio_button_data *bdata = &ddata->data[i];
79 117 int irq;
80 118 unsigned int type = button->type ?: EV_KEY;
81 119  
  120 + bdata->input = input;
  121 + setup_timer(&bdata->timer,
  122 + gpio_check_button, (unsigned long)bdata);
  123 +
82 124 error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
83 125 if (error < 0) {
84 126 pr_err("gpio-keys: failed to request GPIO %d,"
85 127 " error %d\n", button->gpio, error);
86   - goto fail;
  128 + goto fail2;
87 129 }
88 130  
89 131 error = gpio_direction_input(button->gpio);
... ... @@ -92,7 +134,7 @@
92 134 " direction for GPIO %d, error %d\n",
93 135 button->gpio, error);
94 136 gpio_free(button->gpio);
95   - goto fail;
  137 + goto fail2;
96 138 }
97 139  
98 140 irq = gpio_to_irq(button->gpio);
... ... @@ -102,7 +144,7 @@
102 144 " for GPIO %d, error %d\n",
103 145 button->gpio, error);
104 146 gpio_free(button->gpio);
105   - goto fail;
  147 + goto fail2;
106 148 }
107 149  
108 150 error = request_irq(irq, gpio_keys_isr,
... ... @@ -114,7 +156,7 @@
114 156 pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
115 157 irq, error);
116 158 gpio_free(button->gpio);
117   - goto fail;
  159 + goto fail2;
118 160 }
119 161  
120 162 if (button->wakeup)
121 163  
122 164  
123 165  
124 166  
... ... @@ -127,21 +169,25 @@
127 169 if (error) {
128 170 pr_err("gpio-keys: Unable to register input device, "
129 171 "error: %d\n", error);
130   - goto fail;
  172 + goto fail2;
131 173 }
132 174  
133 175 device_init_wakeup(&pdev->dev, wakeup);
134 176  
135 177 return 0;
136 178  
137   - fail:
  179 + fail2:
138 180 while (--i >= 0) {
139 181 free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
  182 + if (pdata->buttons[i].debounce_interval)
  183 + del_timer_sync(&ddata->data[i].timer);
140 184 gpio_free(pdata->buttons[i].gpio);
141 185 }
142 186  
143 187 platform_set_drvdata(pdev, NULL);
  188 + fail1:
144 189 input_free_device(input);
  190 + kfree(ddata);
145 191  
146 192 return error;
147 193 }
... ... @@ -149,7 +195,8 @@
149 195 static int __devexit gpio_keys_remove(struct platform_device *pdev)
150 196 {
151 197 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
152   - struct input_dev *input = platform_get_drvdata(pdev);
  198 + struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
  199 + struct input_dev *input = ddata->input;
153 200 int i;
154 201  
155 202 device_init_wakeup(&pdev->dev, 0);
... ... @@ -157,6 +204,8 @@
157 204 for (i = 0; i < pdata->nbuttons; i++) {
158 205 int irq = gpio_to_irq(pdata->buttons[i].gpio);
159 206 free_irq(irq, pdev);
  207 + if (pdata->buttons[i].debounce_interval)
  208 + del_timer_sync(&ddata->data[i].timer);
160 209 gpio_free(pdata->buttons[i].gpio);
161 210 }
162 211  
include/linux/gpio_keys.h
... ... @@ -9,6 +9,7 @@
9 9 char *desc;
10 10 int type; /* input event type (EV_KEY, EV_SW) */
11 11 int wakeup; /* configure the button as a wake-up source */
  12 + int debounce_interval; /* debounce ticks interval in msecs */
12 13 };
13 14  
14 15 struct gpio_keys_platform_data {