Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/keyboard/gpio_keys_polled.c
15111 views
1
/*
2
* Driver for buttons on GPIO lines not capable of generating interrupts
3
*
4
* Copyright (C) 2007-2010 Gabor Juhos <[email protected]>
5
* Copyright (C) 2010 Nuno Goncalves <[email protected]>
6
*
7
* This file was based on: /drivers/input/misc/cobalt_btns.c
8
* Copyright (C) 2007 Yoichi Yuasa <[email protected]>
9
*
10
* also was based on: /drivers/input/keyboard/gpio_keys.c
11
* Copyright 2005 Phil Blundell
12
*
13
* This program is free software; you can redistribute it and/or modify
14
* it under the terms of the GNU General Public License version 2 as
15
* published by the Free Software Foundation.
16
*/
17
18
#include <linux/kernel.h>
19
#include <linux/module.h>
20
#include <linux/init.h>
21
#include <linux/slab.h>
22
#include <linux/input.h>
23
#include <linux/input-polldev.h>
24
#include <linux/ioport.h>
25
#include <linux/platform_device.h>
26
#include <linux/gpio.h>
27
#include <linux/gpio_keys.h>
28
29
#define DRV_NAME "gpio-keys-polled"
30
31
struct gpio_keys_button_data {
32
int last_state;
33
int count;
34
int threshold;
35
int can_sleep;
36
};
37
38
struct gpio_keys_polled_dev {
39
struct input_polled_dev *poll_dev;
40
struct device *dev;
41
struct gpio_keys_platform_data *pdata;
42
struct gpio_keys_button_data data[0];
43
};
44
45
static void gpio_keys_polled_check_state(struct input_dev *input,
46
struct gpio_keys_button *button,
47
struct gpio_keys_button_data *bdata)
48
{
49
int state;
50
51
if (bdata->can_sleep)
52
state = !!gpio_get_value_cansleep(button->gpio);
53
else
54
state = !!gpio_get_value(button->gpio);
55
56
if (state != bdata->last_state) {
57
unsigned int type = button->type ?: EV_KEY;
58
59
input_event(input, type, button->code,
60
!!(state ^ button->active_low));
61
input_sync(input);
62
bdata->count = 0;
63
bdata->last_state = state;
64
}
65
}
66
67
static void gpio_keys_polled_poll(struct input_polled_dev *dev)
68
{
69
struct gpio_keys_polled_dev *bdev = dev->private;
70
struct gpio_keys_platform_data *pdata = bdev->pdata;
71
struct input_dev *input = dev->input;
72
int i;
73
74
for (i = 0; i < bdev->pdata->nbuttons; i++) {
75
struct gpio_keys_button_data *bdata = &bdev->data[i];
76
77
if (bdata->count < bdata->threshold)
78
bdata->count++;
79
else
80
gpio_keys_polled_check_state(input, &pdata->buttons[i],
81
bdata);
82
}
83
}
84
85
static void gpio_keys_polled_open(struct input_polled_dev *dev)
86
{
87
struct gpio_keys_polled_dev *bdev = dev->private;
88
struct gpio_keys_platform_data *pdata = bdev->pdata;
89
90
if (pdata->enable)
91
pdata->enable(bdev->dev);
92
}
93
94
static void gpio_keys_polled_close(struct input_polled_dev *dev)
95
{
96
struct gpio_keys_polled_dev *bdev = dev->private;
97
struct gpio_keys_platform_data *pdata = bdev->pdata;
98
99
if (pdata->disable)
100
pdata->disable(bdev->dev);
101
}
102
103
static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
104
{
105
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
106
struct device *dev = &pdev->dev;
107
struct gpio_keys_polled_dev *bdev;
108
struct input_polled_dev *poll_dev;
109
struct input_dev *input;
110
int error;
111
int i;
112
113
if (!pdata || !pdata->poll_interval)
114
return -EINVAL;
115
116
bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
117
pdata->nbuttons * sizeof(struct gpio_keys_button_data),
118
GFP_KERNEL);
119
if (!bdev) {
120
dev_err(dev, "no memory for private data\n");
121
return -ENOMEM;
122
}
123
124
poll_dev = input_allocate_polled_device();
125
if (!poll_dev) {
126
dev_err(dev, "no memory for polled device\n");
127
error = -ENOMEM;
128
goto err_free_bdev;
129
}
130
131
poll_dev->private = bdev;
132
poll_dev->poll = gpio_keys_polled_poll;
133
poll_dev->poll_interval = pdata->poll_interval;
134
poll_dev->open = gpio_keys_polled_open;
135
poll_dev->close = gpio_keys_polled_close;
136
137
input = poll_dev->input;
138
139
input->evbit[0] = BIT(EV_KEY);
140
input->name = pdev->name;
141
input->phys = DRV_NAME"/input0";
142
input->dev.parent = &pdev->dev;
143
144
input->id.bustype = BUS_HOST;
145
input->id.vendor = 0x0001;
146
input->id.product = 0x0001;
147
input->id.version = 0x0100;
148
149
for (i = 0; i < pdata->nbuttons; i++) {
150
struct gpio_keys_button *button = &pdata->buttons[i];
151
struct gpio_keys_button_data *bdata = &bdev->data[i];
152
unsigned int gpio = button->gpio;
153
unsigned int type = button->type ?: EV_KEY;
154
155
if (button->wakeup) {
156
dev_err(dev, DRV_NAME " does not support wakeup\n");
157
error = -EINVAL;
158
goto err_free_gpio;
159
}
160
161
error = gpio_request(gpio,
162
button->desc ? button->desc : DRV_NAME);
163
if (error) {
164
dev_err(dev, "unable to claim gpio %u, err=%d\n",
165
gpio, error);
166
goto err_free_gpio;
167
}
168
169
error = gpio_direction_input(gpio);
170
if (error) {
171
dev_err(dev,
172
"unable to set direction on gpio %u, err=%d\n",
173
gpio, error);
174
goto err_free_gpio;
175
}
176
177
bdata->can_sleep = gpio_cansleep(gpio);
178
bdata->last_state = -1;
179
bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
180
pdata->poll_interval);
181
182
input_set_capability(input, type, button->code);
183
}
184
185
bdev->poll_dev = poll_dev;
186
bdev->dev = dev;
187
bdev->pdata = pdata;
188
platform_set_drvdata(pdev, bdev);
189
190
error = input_register_polled_device(poll_dev);
191
if (error) {
192
dev_err(dev, "unable to register polled device, err=%d\n",
193
error);
194
goto err_free_gpio;
195
}
196
197
/* report initial state of the buttons */
198
for (i = 0; i < pdata->nbuttons; i++)
199
gpio_keys_polled_check_state(input, &pdata->buttons[i],
200
&bdev->data[i]);
201
202
return 0;
203
204
err_free_gpio:
205
while (--i >= 0)
206
gpio_free(pdata->buttons[i].gpio);
207
208
input_free_polled_device(poll_dev);
209
210
err_free_bdev:
211
kfree(bdev);
212
213
platform_set_drvdata(pdev, NULL);
214
return error;
215
}
216
217
static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
218
{
219
struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
220
struct gpio_keys_platform_data *pdata = bdev->pdata;
221
int i;
222
223
input_unregister_polled_device(bdev->poll_dev);
224
225
for (i = 0; i < pdata->nbuttons; i++)
226
gpio_free(pdata->buttons[i].gpio);
227
228
input_free_polled_device(bdev->poll_dev);
229
230
kfree(bdev);
231
platform_set_drvdata(pdev, NULL);
232
233
return 0;
234
}
235
236
static struct platform_driver gpio_keys_polled_driver = {
237
.probe = gpio_keys_polled_probe,
238
.remove = __devexit_p(gpio_keys_polled_remove),
239
.driver = {
240
.name = DRV_NAME,
241
.owner = THIS_MODULE,
242
},
243
};
244
245
static int __init gpio_keys_polled_init(void)
246
{
247
return platform_driver_register(&gpio_keys_polled_driver);
248
}
249
250
static void __exit gpio_keys_polled_exit(void)
251
{
252
platform_driver_unregister(&gpio_keys_polled_driver);
253
}
254
255
module_init(gpio_keys_polled_init);
256
module_exit(gpio_keys_polled_exit);
257
258
MODULE_LICENSE("GPL v2");
259
MODULE_AUTHOR("Gabor Juhos <[email protected]>");
260
MODULE_DESCRIPTION("Polled GPIO Buttons driver");
261
MODULE_ALIAS("platform:" DRV_NAME);
262
263