aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans-Christian Egtvedt <hcegtvedt@norway.atmel.com>2007-06-14 23:32:35 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-07-10 00:35:17 -0400
commit5f5655023f2814969b744c1e07494666587243aa (patch)
treedd4d387a5c4505df663a38299901d0cb81f4effa /drivers
parent9657d75c5f0f7d0a9cb507521d3ad1436aea28c9 (diff)
Input: add gpio-mouse driver
Adds support for simulating a mouse using GPIO lines. The driver needs an appropriate platform device to be created by architecture code. The driver has been tested on AT32AP7000 microprocessor using the ATSTK1000 development board. Signed-off-by: Hans-Christian Egtvedt <hcegtvedt@atmel.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/mouse/Kconfig16
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/gpio_mouse.c196
3 files changed, 213 insertions, 0 deletions
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 50e06e8dd05d..7bbea097cda2 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -216,4 +216,20 @@ config MOUSE_HIL
216 help 216 help
217 Say Y here to support HIL pointers. 217 Say Y here to support HIL pointers.
218 218
219config MOUSE_GPIO
220 tristate "GPIO mouse"
221 depends on GENERIC_GPIO
222 select INPUT_POLLDEV
223 help
224 This driver simulates a mouse on GPIO lines of various CPUs (and some
225 other chips).
226
227 Say Y here if your device has buttons or a simple joystick connected
228 directly to GPIO lines. Your board-specific setup logic must also
229 provide a platform device and platform data saying which GPIOs are
230 used.
231
232 To compile this driver as a module, choose M here: the
233 module will be called gpio_mouse.
234
219endif 235endif
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index aa4ba878533f..9e6e36330820 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o
15obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o 15obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
16obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o 16obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
17obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o 17obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
18obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
18 19
19psmouse-objs := psmouse-base.o synaptics.o 20psmouse-objs := psmouse-base.o synaptics.o
20 21
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
new file mode 100644
index 000000000000..0936d6ba015c
--- /dev/null
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -0,0 +1,196 @@
1/*
2 * Driver for simulating a mouse on GPIO lines.
3 *
4 * Copyright (C) 2007 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/init.h>
12#include <linux/version.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/input-polldev.h>
16#include <linux/gpio_mouse.h>
17
18#include <asm/gpio.h>
19
20/*
21 * Timer function which is run every scan_ms ms when the device is opened.
22 * The dev input varaible is set to the the input_dev pointer.
23 */
24static void gpio_mouse_scan(struct input_polled_dev *dev)
25{
26 struct gpio_mouse_platform_data *gpio = dev->private;
27 struct input_dev *input = dev->input;
28 int x, y;
29
30 if (gpio->bleft >= 0)
31 input_report_key(input, BTN_LEFT,
32 gpio_get_value(gpio->bleft) ^ gpio->polarity);
33 if (gpio->bmiddle >= 0)
34 input_report_key(input, BTN_MIDDLE,
35 gpio_get_value(gpio->bmiddle) ^ gpio->polarity);
36 if (gpio->bright >= 0)
37 input_report_key(input, BTN_RIGHT,
38 gpio_get_value(gpio->bright) ^ gpio->polarity);
39
40 x = (gpio_get_value(gpio->right) ^ gpio->polarity)
41 - (gpio_get_value(gpio->left) ^ gpio->polarity);
42 y = (gpio_get_value(gpio->down) ^ gpio->polarity)
43 - (gpio_get_value(gpio->up) ^ gpio->polarity);
44
45 input_report_rel(input, REL_X, x);
46 input_report_rel(input, REL_Y, y);
47 input_sync(input);
48}
49
50static int __init gpio_mouse_probe(struct platform_device *pdev)
51{
52 struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
53 struct input_polled_dev *input_poll;
54 struct input_dev *input;
55 int pin, i;
56 int error;
57
58 if (!pdata) {
59 dev_err(&pdev->dev, "no platform data\n");
60 error = -ENXIO;
61 goto out;
62 }
63
64 if (pdata->scan_ms < 0) {
65 dev_err(&pdev->dev, "invalid scan time\n");
66 error = -EINVAL;
67 goto out;
68 }
69
70 for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
71 pin = pdata->pins[i];
72
73 if (pin < 0) {
74
75 if (i <= GPIO_MOUSE_PIN_RIGHT) {
76 /* Mouse direction is required. */
77 dev_err(&pdev->dev,
78 "missing GPIO for directions\n");
79 error = -EINVAL;
80 goto out_free_gpios;
81 }
82
83 if (i == GPIO_MOUSE_PIN_BLEFT)
84 dev_dbg(&pdev->dev, "no left button defined\n");
85
86 } else {
87 error = gpio_request(pin, "gpio_mouse");
88 if (error) {
89 dev_err(&pdev->dev, "fail %d pin (%d idx)\n",
90 pin, i);
91 goto out_free_gpios;
92 }
93
94 gpio_direction_input(pin);
95 }
96 }
97
98 input_poll = input_allocate_polled_device();
99 if (!input_poll) {
100 dev_err(&pdev->dev, "not enough memory for input device\n");
101 error = -ENOMEM;
102 goto out_free_gpios;
103 }
104
105 platform_set_drvdata(pdev, input_poll);
106
107 /* set input-polldev handlers */
108 input_poll->private = pdata;
109 input_poll->poll = gpio_mouse_scan;
110 input_poll->poll_interval = pdata->scan_ms;
111
112 input = input_poll->input;
113 input->name = pdev->name;
114 input->id.bustype = BUS_HOST;
115 input->dev.parent = &pdev->dev;
116
117 input_set_capability(input, EV_REL, REL_X);
118 input_set_capability(input, EV_REL, REL_Y);
119 if (pdata->bleft >= 0)
120 input_set_capability(input, EV_KEY, BTN_LEFT);
121 if (pdata->bmiddle >= 0)
122 input_set_capability(input, EV_KEY, BTN_MIDDLE);
123 if (pdata->bright >= 0)
124 input_set_capability(input, EV_KEY, BTN_RIGHT);
125
126 error = input_register_polled_device(input_poll);
127 if (error) {
128 dev_err(&pdev->dev, "could not register input device\n");
129 goto out_free_polldev;
130 }
131
132 dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n",
133 pdata->scan_ms,
134 pdata->bleft < 0 ? "" : "left ",
135 pdata->bmiddle < 0 ? "" : "middle ",
136 pdata->bright < 0 ? "" : "right");
137
138 return 0;
139
140 out_free_polldev:
141 input_free_polled_device(input_poll);
142 platform_set_drvdata(pdev, NULL);
143
144 out_free_gpios:
145 while (--i >= 0) {
146 pin = pdata->pins[i];
147 if (pin)
148 gpio_free(pin);
149 }
150 out:
151 return error;
152}
153
154static int __devexit gpio_mouse_remove(struct platform_device *pdev)
155{
156 struct input_polled_dev *input = platform_get_drvdata(pdev);
157 struct gpio_mouse_platform_data *pdata = input->private;
158 int pin, i;
159
160 input_unregister_polled_device(input);
161 input_free_polled_device(input);
162
163 for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
164 pin = pdata->pins[i];
165 if (pin >= 0)
166 gpio_free(pin);
167 }
168
169 platform_set_drvdata(pdev, NULL);
170
171 return 0;
172}
173
174struct platform_driver gpio_mouse_device_driver = {
175 .remove = __devexit_p(gpio_mouse_remove),
176 .driver = {
177 .name = "gpio_mouse",
178 }
179};
180
181static int __init gpio_mouse_init(void)
182{
183 return platform_driver_probe(&gpio_mouse_device_driver,
184 gpio_mouse_probe);
185}
186module_init(gpio_mouse_init);
187
188static void __exit gpio_mouse_exit(void)
189{
190 platform_driver_unregister(&gpio_mouse_device_driver);
191}
192module_exit(gpio_mouse_exit);
193
194MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
195MODULE_DESCRIPTION("GPIO mouse driver");
196MODULE_LICENSE("GPL");