Initial commit
[kernel/linux-3.0.git] / drivers / input / misc / gpio_event.c
1 /* drivers/input/misc/gpio_event.c
2  *
3  * Copyright (C) 2007 Google, Inc.
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15
16 #include <linux/earlysuspend.h>
17 #include <linux/module.h>
18 #include <linux/input.h>
19 #include <linux/gpio_event.h>
20 #include <linux/hrtimer.h>
21 #include <linux/platform_device.h>
22 #include <linux/slab.h>
23
24 struct gpio_event {
25         struct gpio_event_input_devs *input_devs;
26         const struct gpio_event_platform_data *info;
27         struct early_suspend early_suspend;
28         void *state[0];
29 };
30
31 static int gpio_input_event(
32         struct input_dev *dev, unsigned int type, unsigned int code, int value)
33 {
34         int i;
35         int devnr;
36         int ret = 0;
37         int tmp_ret;
38         struct gpio_event_info **ii;
39         struct gpio_event *ip = input_get_drvdata(dev);
40
41         for (devnr = 0; devnr < ip->input_devs->count; devnr++)
42                 if (ip->input_devs->dev[devnr] == dev)
43                         break;
44         if (devnr == ip->input_devs->count) {
45                 pr_err("gpio_input_event: unknown device %p\n", dev);
46                 return -EIO;
47         }
48
49         for (i = 0, ii = ip->info->info; i < ip->info->info_count; i++, ii++) {
50                 if ((*ii)->event) {
51                         tmp_ret = (*ii)->event(ip->input_devs, *ii,
52                                                 &ip->state[i],
53                                                 devnr, type, code, value);
54                         if (tmp_ret)
55                                 ret = tmp_ret;
56                 }
57         }
58         return ret;
59 }
60
61 static int gpio_event_call_all_func(struct gpio_event *ip, int func)
62 {
63         int i;
64         int ret;
65         struct gpio_event_info **ii;
66
67         if (func == GPIO_EVENT_FUNC_INIT || func == GPIO_EVENT_FUNC_RESUME) {
68                 ii = ip->info->info;
69                 for (i = 0; i < ip->info->info_count; i++, ii++) {
70                         if ((*ii)->func == NULL) {
71                                 ret = -ENODEV;
72                                 pr_err("gpio_event_probe: Incomplete pdata, "
73                                         "no function\n");
74                                 goto err_no_func;
75                         }
76                         if (func == GPIO_EVENT_FUNC_RESUME && (*ii)->no_suspend)
77                                 continue;
78                         ret = (*ii)->func(ip->input_devs, *ii, &ip->state[i],
79                                           func);
80                         if (ret) {
81                                 pr_err("gpio_event_probe: function failed\n");
82                                 goto err_func_failed;
83                         }
84                 }
85                 return 0;
86         }
87
88         ret = 0;
89         i = ip->info->info_count;
90         ii = ip->info->info + i;
91         while (i > 0) {
92                 i--;
93                 ii--;
94                 if ((func & ~1) == GPIO_EVENT_FUNC_SUSPEND && (*ii)->no_suspend)
95                         continue;
96                 (*ii)->func(ip->input_devs, *ii, &ip->state[i], func & ~1);
97 err_func_failed:
98 err_no_func:
99                 ;
100         }
101         return ret;
102 }
103
104 #ifdef CONFIG_HAS_EARLYSUSPEND
105 void gpio_event_suspend(struct early_suspend *h)
106 {
107         struct gpio_event *ip;
108         ip = container_of(h, struct gpio_event, early_suspend);
109         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_SUSPEND);
110         ip->info->power(ip->info, 0);
111 }
112
113 void gpio_event_resume(struct early_suspend *h)
114 {
115         struct gpio_event *ip;
116         ip = container_of(h, struct gpio_event, early_suspend);
117         ip->info->power(ip->info, 1);
118         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_RESUME);
119 }
120 #endif
121
122 static int gpio_event_probe(struct platform_device *pdev)
123 {
124         int err;
125         struct gpio_event *ip;
126         struct gpio_event_platform_data *event_info;
127         int dev_count = 1;
128         int i;
129         int registered = 0;
130
131         event_info = pdev->dev.platform_data;
132         if (event_info == NULL) {
133                 pr_err("gpio_event_probe: No pdata\n");
134                 return -ENODEV;
135         }
136         if ((!event_info->name && !event_info->names[0]) ||
137             !event_info->info || !event_info->info_count) {
138                 pr_err("gpio_event_probe: Incomplete pdata\n");
139                 return -ENODEV;
140         }
141         if (!event_info->name)
142                 while (event_info->names[dev_count])
143                         dev_count++;
144         ip = kzalloc(sizeof(*ip) +
145                      sizeof(ip->state[0]) * event_info->info_count +
146                      sizeof(*ip->input_devs) +
147                      sizeof(ip->input_devs->dev[0]) * dev_count, GFP_KERNEL);
148         if (ip == NULL) {
149                 err = -ENOMEM;
150                 pr_err("gpio_event_probe: Failed to allocate private data\n");
151                 goto err_kp_alloc_failed;
152         }
153         ip->input_devs = (void*)&ip->state[event_info->info_count];
154         platform_set_drvdata(pdev, ip);
155
156         for (i = 0; i < dev_count; i++) {
157                 struct input_dev *input_dev = input_allocate_device();
158                 if (input_dev == NULL) {
159                         err = -ENOMEM;
160                         pr_err("gpio_event_probe: "
161                                 "Failed to allocate input device\n");
162                         goto err_input_dev_alloc_failed;
163                 }
164                 input_set_drvdata(input_dev, ip);
165                 input_dev->name = event_info->name ?
166                                         event_info->name : event_info->names[i];
167                 input_dev->event = gpio_input_event;
168                 ip->input_devs->dev[i] = input_dev;
169         }
170         ip->input_devs->count = dev_count;
171         ip->info = event_info;
172         if (event_info->power) {
173 #ifdef CONFIG_HAS_EARLYSUSPEND
174                 ip->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
175                 ip->early_suspend.suspend = gpio_event_suspend;
176                 ip->early_suspend.resume = gpio_event_resume;
177                 register_early_suspend(&ip->early_suspend);
178 #endif
179                 ip->info->power(ip->info, 1);
180         }
181
182         err = gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_INIT);
183         if (err)
184                 goto err_call_all_func_failed;
185
186         for (i = 0; i < dev_count; i++) {
187                 err = input_register_device(ip->input_devs->dev[i]);
188                 if (err) {
189                         pr_err("gpio_event_probe: Unable to register %s "
190                                 "input device\n", ip->input_devs->dev[i]->name);
191                         goto err_input_register_device_failed;
192                 }
193                 registered++;
194         }
195
196         return 0;
197
198 err_input_register_device_failed:
199         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
200 err_call_all_func_failed:
201         if (event_info->power) {
202 #ifdef CONFIG_HAS_EARLYSUSPEND
203                 unregister_early_suspend(&ip->early_suspend);
204 #endif
205                 ip->info->power(ip->info, 0);
206         }
207         for (i = 0; i < registered; i++)
208                 input_unregister_device(ip->input_devs->dev[i]);
209         for (i = dev_count - 1; i >= registered; i--) {
210                 input_free_device(ip->input_devs->dev[i]);
211 err_input_dev_alloc_failed:
212                 ;
213         }
214         kfree(ip);
215 err_kp_alloc_failed:
216         return err;
217 }
218
219 static int gpio_event_remove(struct platform_device *pdev)
220 {
221         struct gpio_event *ip = platform_get_drvdata(pdev);
222         int i;
223
224         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
225         if (ip->info->power) {
226 #ifdef CONFIG_HAS_EARLYSUSPEND
227                 unregister_early_suspend(&ip->early_suspend);
228 #endif
229                 ip->info->power(ip->info, 0);
230         }
231         for (i = 0; i < ip->input_devs->count; i++)
232                 input_unregister_device(ip->input_devs->dev[i]);
233         kfree(ip);
234         return 0;
235 }
236
237 static struct platform_driver gpio_event_driver = {
238         .probe          = gpio_event_probe,
239         .remove         = gpio_event_remove,
240         .driver         = {
241                 .name   = GPIO_EVENT_DEV_NAME,
242         },
243 };
244
245 static int __devinit gpio_event_init(void)
246 {
247         return platform_driver_register(&gpio_event_driver);
248 }
249
250 static void __exit gpio_event_exit(void)
251 {
252         platform_driver_unregister(&gpio_event_driver);
253 }
254
255 module_init(gpio_event_init);
256 module_exit(gpio_event_exit);
257
258 MODULE_DESCRIPTION("GPIO Event Driver");
259 MODULE_LICENSE("GPL");
260