• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/input/mouse/
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/module.h>
13#include <linux/platform_device.h>
14#include <linux/input-polldev.h>
15#include <linux/gpio_mouse.h>
16
17#include <asm/gpio.h>
18
19/*
20 * Timer function which is run every scan_ms ms when the device is opened.
21 * The dev input variable is set to the the input_dev pointer.
22 */
23static void gpio_mouse_scan(struct input_polled_dev *dev)
24{
25	struct gpio_mouse_platform_data *gpio = dev->private;
26	struct input_dev *input = dev->input;
27	int x, y;
28
29	if (gpio->bleft >= 0)
30		input_report_key(input, BTN_LEFT,
31				gpio_get_value(gpio->bleft) ^ gpio->polarity);
32	if (gpio->bmiddle >= 0)
33		input_report_key(input, BTN_MIDDLE,
34				gpio_get_value(gpio->bmiddle) ^ gpio->polarity);
35	if (gpio->bright >= 0)
36		input_report_key(input, BTN_RIGHT,
37				gpio_get_value(gpio->bright) ^ gpio->polarity);
38
39	x = (gpio_get_value(gpio->right) ^ gpio->polarity)
40		- (gpio_get_value(gpio->left) ^ gpio->polarity);
41	y = (gpio_get_value(gpio->down) ^ gpio->polarity)
42		- (gpio_get_value(gpio->up) ^ gpio->polarity);
43
44	input_report_rel(input, REL_X, x);
45	input_report_rel(input, REL_Y, y);
46	input_sync(input);
47}
48
49static int __devinit gpio_mouse_probe(struct platform_device *pdev)
50{
51	struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
52	struct input_polled_dev *input_poll;
53	struct input_dev *input;
54	int pin, i;
55	int error;
56
57	if (!pdata) {
58		dev_err(&pdev->dev, "no platform data\n");
59		error = -ENXIO;
60		goto out;
61	}
62
63	if (pdata->scan_ms < 0) {
64		dev_err(&pdev->dev, "invalid scan time\n");
65		error = -EINVAL;
66		goto out;
67	}
68
69	for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
70		pin = pdata->pins[i];
71
72		if (pin < 0) {
73
74			if (i <= GPIO_MOUSE_PIN_RIGHT) {
75				/* Mouse direction is required. */
76				dev_err(&pdev->dev,
77					"missing GPIO for directions\n");
78				error = -EINVAL;
79				goto out_free_gpios;
80			}
81
82			if (i == GPIO_MOUSE_PIN_BLEFT)
83				dev_dbg(&pdev->dev, "no left button defined\n");
84
85		} else {
86			error = gpio_request(pin, "gpio_mouse");
87			if (error) {
88				dev_err(&pdev->dev, "fail %d pin (%d idx)\n",
89					pin, i);
90				goto out_free_gpios;
91			}
92
93			gpio_direction_input(pin);
94		}
95	}
96
97	input_poll = input_allocate_polled_device();
98	if (!input_poll) {
99		dev_err(&pdev->dev, "not enough memory for input device\n");
100		error = -ENOMEM;
101		goto out_free_gpios;
102	}
103
104	platform_set_drvdata(pdev, input_poll);
105
106	/* set input-polldev handlers */
107	input_poll->private = pdata;
108	input_poll->poll = gpio_mouse_scan;
109	input_poll->poll_interval = pdata->scan_ms;
110
111	input = input_poll->input;
112	input->name = pdev->name;
113	input->id.bustype = BUS_HOST;
114	input->dev.parent = &pdev->dev;
115
116	input_set_capability(input, EV_REL, REL_X);
117	input_set_capability(input, EV_REL, REL_Y);
118	if (pdata->bleft >= 0)
119		input_set_capability(input, EV_KEY, BTN_LEFT);
120	if (pdata->bmiddle >= 0)
121		input_set_capability(input, EV_KEY, BTN_MIDDLE);
122	if (pdata->bright >= 0)
123		input_set_capability(input, EV_KEY, BTN_RIGHT);
124
125	error = input_register_polled_device(input_poll);
126	if (error) {
127		dev_err(&pdev->dev, "could not register input device\n");
128		goto out_free_polldev;
129	}
130
131	dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n",
132			pdata->scan_ms,
133			pdata->bleft < 0 ? "" : "left ",
134			pdata->bmiddle < 0 ? "" : "middle ",
135			pdata->bright < 0 ? "" : "right");
136
137	return 0;
138
139 out_free_polldev:
140	input_free_polled_device(input_poll);
141	platform_set_drvdata(pdev, NULL);
142
143 out_free_gpios:
144	while (--i >= 0) {
145		pin = pdata->pins[i];
146		if (pin)
147			gpio_free(pin);
148	}
149 out:
150	return error;
151}
152
153static int __devexit gpio_mouse_remove(struct platform_device *pdev)
154{
155	struct input_polled_dev *input = platform_get_drvdata(pdev);
156	struct gpio_mouse_platform_data *pdata = input->private;
157	int pin, i;
158
159	input_unregister_polled_device(input);
160	input_free_polled_device(input);
161
162	for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
163		pin = pdata->pins[i];
164		if (pin >= 0)
165			gpio_free(pin);
166	}
167
168	platform_set_drvdata(pdev, NULL);
169
170	return 0;
171}
172
173static struct platform_driver gpio_mouse_device_driver = {
174	.probe		= gpio_mouse_probe,
175	.remove		= __devexit_p(gpio_mouse_remove),
176	.driver		= {
177		.name	= "gpio_mouse",
178		.owner	= THIS_MODULE,
179	}
180};
181
182static int __init gpio_mouse_init(void)
183{
184	return platform_driver_register(&gpio_mouse_device_driver);
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");
197MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */
198