aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/keyboard/gpio_keys.c318
-rw-r--r--include/linux/gpio_keys.h1
2 files changed, 308 insertions, 11 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 1aff3b76effd..2b708aa85553 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -30,13 +30,289 @@ struct gpio_button_data {
30 struct input_dev *input; 30 struct input_dev *input;
31 struct timer_list timer; 31 struct timer_list timer;
32 struct work_struct work; 32 struct work_struct work;
33 bool disabled;
33}; 34};
34 35
35struct gpio_keys_drvdata { 36struct gpio_keys_drvdata {
36 struct input_dev *input; 37 struct input_dev *input;
38 struct mutex disable_lock;
39 unsigned int n_buttons;
37 struct gpio_button_data data[0]; 40 struct gpio_button_data data[0];
38}; 41};
39 42
43/*
44 * SYSFS interface for enabling/disabling keys and switches:
45 *
46 * There are 4 attributes under /sys/devices/platform/gpio-keys/
47 * keys [ro] - bitmap of keys (EV_KEY) which can be
48 * disabled
49 * switches [ro] - bitmap of switches (EV_SW) which can be
50 * disabled
51 * disabled_keys [rw] - bitmap of keys currently disabled
52 * disabled_switches [rw] - bitmap of switches currently disabled
53 *
54 * Userland can change these values and hence disable event generation
55 * for each key (or switch). Disabling a key means its interrupt line
56 * is disabled.
57 *
58 * For example, if we have following switches set up as gpio-keys:
59 * SW_DOCK = 5
60 * SW_CAMERA_LENS_COVER = 9
61 * SW_KEYPAD_SLIDE = 10
62 * SW_FRONT_PROXIMITY = 11
63 * This is read from switches:
64 * 11-9,5
65 * Next we want to disable proximity (11) and dock (5), we write:
66 * 11,5
67 * to file disabled_switches. Now proximity and dock IRQs are disabled.
68 * This can be verified by reading the file disabled_switches:
69 * 11,5
70 * If we now want to enable proximity (11) switch we write:
71 * 5
72 * to disabled_switches.
73 *
74 * We can disable only those keys which don't allow sharing the irq.
75 */
76
77/**
78 * get_n_events_by_type() - returns maximum number of events per @type
79 * @type: type of button (%EV_KEY, %EV_SW)
80 *
81 * Return value of this function can be used to allocate bitmap
82 * large enough to hold all bits for given type.
83 */
84static inline int get_n_events_by_type(int type)
85{
86 BUG_ON(type != EV_SW && type != EV_KEY);
87
88 return (type == EV_KEY) ? KEY_CNT : SW_CNT;
89}
90
91/**
92 * gpio_keys_disable_button() - disables given GPIO button
93 * @bdata: button data for button to be disabled
94 *
95 * Disables button pointed by @bdata. This is done by masking
96 * IRQ line. After this function is called, button won't generate
97 * input events anymore. Note that one can only disable buttons
98 * that don't share IRQs.
99 *
100 * Make sure that @bdata->disable_lock is locked when entering
101 * this function to avoid races when concurrent threads are
102 * disabling buttons at the same time.
103 */
104static void gpio_keys_disable_button(struct gpio_button_data *bdata)
105{
106 if (!bdata->disabled) {
107 /*
108 * Disable IRQ and possible debouncing timer.
109 */
110 disable_irq(gpio_to_irq(bdata->button->gpio));
111 if (bdata->button->debounce_interval)
112 del_timer_sync(&bdata->timer);
113
114 bdata->disabled = true;
115 }
116}
117
118/**
119 * gpio_keys_enable_button() - enables given GPIO button
120 * @bdata: button data for button to be disabled
121 *
122 * Enables given button pointed by @bdata.
123 *
124 * Make sure that @bdata->disable_lock is locked when entering
125 * this function to avoid races with concurrent threads trying
126 * to enable the same button at the same time.
127 */
128static void gpio_keys_enable_button(struct gpio_button_data *bdata)
129{
130 if (bdata->disabled) {
131 enable_irq(gpio_to_irq(bdata->button->gpio));
132 bdata->disabled = false;
133 }
134}
135
136/**
137 * gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons
138 * @ddata: pointer to drvdata
139 * @buf: buffer where stringified bitmap is written
140 * @type: button type (%EV_KEY, %EV_SW)
141 * @only_disabled: does caller want only those buttons that are
142 * currently disabled or all buttons that can be
143 * disabled
144 *
145 * This function writes buttons that can be disabled to @buf. If
146 * @only_disabled is true, then @buf contains only those buttons
147 * that are currently disabled. Returns 0 on success or negative
148 * errno on failure.
149 */
150static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
151 char *buf, unsigned int type,
152 bool only_disabled)
153{
154 int n_events = get_n_events_by_type(type);
155 unsigned long *bits;
156 ssize_t ret;
157 int i;
158
159 bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL);
160 if (!bits)
161 return -ENOMEM;
162
163 for (i = 0; i < ddata->n_buttons; i++) {
164 struct gpio_button_data *bdata = &ddata->data[i];
165
166 if (bdata->button->type != type)
167 continue;
168
169 if (only_disabled && !bdata->disabled)
170 continue;
171
172 __set_bit(bdata->button->code, bits);
173 }
174
175 ret = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, bits, n_events);
176 buf[ret++] = '\n';
177 buf[ret] = '\0';
178
179 kfree(bits);
180
181 return ret;
182}
183
184/**
185 * gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap
186 * @ddata: pointer to drvdata
187 * @buf: buffer from userspace that contains stringified bitmap
188 * @type: button type (%EV_KEY, %EV_SW)
189 *
190 * This function parses stringified bitmap from @buf and disables/enables
191 * GPIO buttons accordinly. Returns 0 on success and negative error
192 * on failure.
193 */
194static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
195 const char *buf, unsigned int type)
196{
197 int n_events = get_n_events_by_type(type);
198 unsigned long *bits;
199 ssize_t error;
200 int i;
201
202 bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL);
203 if (!bits)
204 return -ENOMEM;
205
206 error = bitmap_parselist(buf, bits, n_events);
207 if (error)
208 goto out;
209
210 /* First validate */
211 for (i = 0; i < ddata->n_buttons; i++) {
212 struct gpio_button_data *bdata = &ddata->data[i];
213
214 if (bdata->button->type != type)
215 continue;
216
217 if (test_bit(bdata->button->code, bits) &&
218 !bdata->button->can_disable) {
219 error = -EINVAL;
220 goto out;
221 }
222 }
223
224 mutex_lock(&ddata->disable_lock);
225
226 for (i = 0; i < ddata->n_buttons; i++) {
227 struct gpio_button_data *bdata = &ddata->data[i];
228
229 if (bdata->button->type != type)
230 continue;
231
232 if (test_bit(bdata->button->code, bits))
233 gpio_keys_disable_button(bdata);
234 else
235 gpio_keys_enable_button(bdata);
236 }
237
238 mutex_unlock(&ddata->disable_lock);
239
240out:
241 kfree(bits);
242 return error;
243}
244
245#define ATTR_SHOW_FN(name, type, only_disabled) \
246static ssize_t gpio_keys_show_##name(struct device *dev, \
247 struct device_attribute *attr, \
248 char *buf) \
249{ \
250 struct platform_device *pdev = to_platform_device(dev); \
251 struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \
252 \
253 return gpio_keys_attr_show_helper(ddata, buf, \
254 type, only_disabled); \
255}
256
257ATTR_SHOW_FN(keys, EV_KEY, false);
258ATTR_SHOW_FN(switches, EV_SW, false);
259ATTR_SHOW_FN(disabled_keys, EV_KEY, true);
260ATTR_SHOW_FN(disabled_switches, EV_SW, true);
261
262/*
263 * ATTRIBUTES:
264 *
265 * /sys/devices/platform/gpio-keys/keys [ro]
266 * /sys/devices/platform/gpio-keys/switches [ro]
267 */
268static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL);
269static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL);
270
271#define ATTR_STORE_FN(name, type) \
272static ssize_t gpio_keys_store_##name(struct device *dev, \
273 struct device_attribute *attr, \
274 const char *buf, \
275 size_t count) \
276{ \
277 struct platform_device *pdev = to_platform_device(dev); \
278 struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \
279 ssize_t error; \
280 \
281 error = gpio_keys_attr_store_helper(ddata, buf, type); \
282 if (error) \
283 return error; \
284 \
285 return count; \
286}
287
288ATTR_STORE_FN(disabled_keys, EV_KEY);
289ATTR_STORE_FN(disabled_switches, EV_SW);
290
291/*
292 * ATTRIBUTES:
293 *
294 * /sys/devices/platform/gpio-keys/disabled_keys [rw]
295 * /sys/devices/platform/gpio-keys/disables_switches [rw]
296 */
297static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO,
298 gpio_keys_show_disabled_keys,
299 gpio_keys_store_disabled_keys);
300static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO,
301 gpio_keys_show_disabled_switches,
302 gpio_keys_store_disabled_switches);
303
304static struct attribute *gpio_keys_attrs[] = {
305 &dev_attr_keys.attr,
306 &dev_attr_switches.attr,
307 &dev_attr_disabled_keys.attr,
308 &dev_attr_disabled_switches.attr,
309 NULL,
310};
311
312static struct attribute_group gpio_keys_attr_group = {
313 .attrs = gpio_keys_attrs,
314};
315
40static void gpio_keys_report_event(struct gpio_button_data *bdata) 316static void gpio_keys_report_event(struct gpio_button_data *bdata)
41{ 317{
42 struct gpio_keys_button *button = bdata->button; 318 struct gpio_keys_button *button = bdata->button;
@@ -79,11 +355,13 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
79 return IRQ_HANDLED; 355 return IRQ_HANDLED;
80} 356}
81 357
82static int __devinit gpio_keys_setup_key(struct device *dev, 358static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
83 struct gpio_button_data *bdata, 359 struct gpio_button_data *bdata,
84 struct gpio_keys_button *button) 360 struct gpio_keys_button *button)
85{ 361{
86 char *desc = button->desc ? button->desc : "gpio_keys"; 362 char *desc = button->desc ? button->desc : "gpio_keys";
363 struct device *dev = &pdev->dev;
364 unsigned long irqflags;
87 int irq, error; 365 int irq, error;
88 366
89 setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata); 367 setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata);
@@ -112,10 +390,15 @@ static int __devinit gpio_keys_setup_key(struct device *dev,
112 goto fail3; 390 goto fail3;
113 } 391 }
114 392
115 error = request_irq(irq, gpio_keys_isr, 393 irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
116 IRQF_SHARED | 394 /*
117 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 395 * If platform has specified that the button can be disabled,
118 desc, bdata); 396 * we don't want it to share the interrupt line.
397 */
398 if (!button->can_disable)
399 irqflags |= IRQF_SHARED;
400
401 error = request_irq(irq, gpio_keys_isr, irqflags, desc, bdata);
119 if (error) { 402 if (error) {
120 dev_err(dev, "Unable to claim irq %d; error %d\n", 403 dev_err(dev, "Unable to claim irq %d; error %d\n",
121 irq, error); 404 irq, error);
@@ -149,6 +432,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
149 goto fail1; 432 goto fail1;
150 } 433 }
151 434
435 ddata->input = input;
436 ddata->n_buttons = pdata->nbuttons;
437 mutex_init(&ddata->disable_lock);
438
152 platform_set_drvdata(pdev, ddata); 439 platform_set_drvdata(pdev, ddata);
153 440
154 input->name = pdev->name; 441 input->name = pdev->name;
@@ -164,8 +451,6 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
164 if (pdata->rep) 451 if (pdata->rep)
165 __set_bit(EV_REP, input->evbit); 452 __set_bit(EV_REP, input->evbit);
166 453
167 ddata->input = input;
168
169 for (i = 0; i < pdata->nbuttons; i++) { 454 for (i = 0; i < pdata->nbuttons; i++) {
170 struct gpio_keys_button *button = &pdata->buttons[i]; 455 struct gpio_keys_button *button = &pdata->buttons[i];
171 struct gpio_button_data *bdata = &ddata->data[i]; 456 struct gpio_button_data *bdata = &ddata->data[i];
@@ -174,7 +459,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
174 bdata->input = input; 459 bdata->input = input;
175 bdata->button = button; 460 bdata->button = button;
176 461
177 error = gpio_keys_setup_key(dev, bdata, button); 462 error = gpio_keys_setup_key(pdev, bdata, button);
178 if (error) 463 if (error)
179 goto fail2; 464 goto fail2;
180 465
@@ -184,13 +469,20 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
184 input_set_capability(input, type, button->code); 469 input_set_capability(input, type, button->code);
185 } 470 }
186 471
187 error = input_register_device(input); 472 error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group);
188 if (error) { 473 if (error) {
189 dev_err(dev, "Unable to register input device, " 474 dev_err(dev, "Unable to export keys/switches, error: %d\n",
190 "error: %d\n", error); 475 error);
191 goto fail2; 476 goto fail2;
192 } 477 }
193 478
479 error = input_register_device(input);
480 if (error) {
481 dev_err(dev, "Unable to register input device, error: %d\n",
482 error);
483 goto fail3;
484 }
485
194 /* get current state of buttons */ 486 /* get current state of buttons */
195 for (i = 0; i < pdata->nbuttons; i++) 487 for (i = 0; i < pdata->nbuttons; i++)
196 gpio_keys_report_event(&ddata->data[i]); 488 gpio_keys_report_event(&ddata->data[i]);
@@ -200,6 +492,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
200 492
201 return 0; 493 return 0;
202 494
495 fail3:
496 sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
203 fail2: 497 fail2:
204 while (--i >= 0) { 498 while (--i >= 0) {
205 free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); 499 free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
@@ -224,6 +518,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
224 struct input_dev *input = ddata->input; 518 struct input_dev *input = ddata->input;
225 int i; 519 int i;
226 520
521 sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
522
227 device_init_wakeup(&pdev->dev, 0); 523 device_init_wakeup(&pdev->dev, 0);
228 524
229 for (i = 0; i < pdata->nbuttons; i++) { 525 for (i = 0; i < pdata->nbuttons; i++) {
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index 1289fa7623ca..cd0b3f30f48e 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -10,6 +10,7 @@ struct gpio_keys_button {
10 int type; /* input event type (EV_KEY, EV_SW) */ 10 int type; /* input event type (EV_KEY, EV_SW) */
11 int wakeup; /* configure the button as a wake-up source */ 11 int wakeup; /* configure the button as a wake-up source */
12 int debounce_interval; /* debounce ticks interval in msecs */ 12 int debounce_interval; /* debounce ticks interval in msecs */
13 bool can_disable;
13}; 14};
14 15
15struct gpio_keys_platform_data { 16struct gpio_keys_platform_data {