]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/dream/gpio_event.c
97a511d11f49f168f2c973f68ef604b00e620f3d
[net-next-2.6.git] / drivers / staging / dream / 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
17 #include <linux/slab.h>
18 #include <linux/module.h>
19 #include <linux/input.h>
20 #include <linux/gpio_event.h>
21 #include <linux/hrtimer.h>
22 #include <linux/platform_device.h>
23
24 struct gpio_event {
25         struct input_dev *input_dev;
26         const struct gpio_event_platform_data *info;
27         void *state[0];
28 };
29
30 static int gpio_input_event(
31         struct input_dev *dev, unsigned int type, unsigned int code, int value)
32 {
33         int i;
34         int ret = 0;
35         int tmp_ret;
36         struct gpio_event_info **ii;
37         struct gpio_event *ip = input_get_drvdata(dev);
38
39         for (i = 0, ii = ip->info->info; i < ip->info->info_count; i++, ii++) {
40                 if ((*ii)->event) {
41                         tmp_ret = (*ii)->event(ip->input_dev, *ii,
42                                         &ip->state[i], type, code, value);
43                         if (tmp_ret)
44                                 ret = tmp_ret;
45                 }
46         }
47         return ret;
48 }
49
50 static int gpio_event_call_all_func(struct gpio_event *ip, int func)
51 {
52         int i;
53         int ret;
54         struct gpio_event_info **ii;
55
56         if (func == GPIO_EVENT_FUNC_INIT || func == GPIO_EVENT_FUNC_RESUME) {
57                 ii = ip->info->info;
58                 for (i = 0; i < ip->info->info_count; i++, ii++) {
59                         if ((*ii)->func == NULL) {
60                                 ret = -ENODEV;
61                                 pr_err("gpio_event_probe: Incomplete pdata, "
62                                         "no function\n");
63                                 goto err_no_func;
64                         }
65                         ret = (*ii)->func(ip->input_dev, *ii, &ip->state[i],
66                                           func);
67                         if (ret) {
68                                 pr_err("gpio_event_probe: function failed\n");
69                                 goto err_func_failed;
70                         }
71                 }
72                 return 0;
73         }
74
75         ret = 0;
76         i = ip->info->info_count;
77         ii = ip->info->info + i;
78         while (i > 0) {
79                 i--;
80                 ii--;
81                 (*ii)->func(ip->input_dev, *ii, &ip->state[i], func & ~1);
82 err_func_failed:
83 err_no_func:
84                 ;
85         }
86         return ret;
87 }
88
89 #ifdef CONFIG_HAS_EARLYSUSPEND
90 void gpio_event_suspend(struct early_suspend *h)
91 {
92         struct gpio_event *ip;
93         ip = container_of(h, struct gpio_event, early_suspend);
94         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_SUSPEND);
95         ip->info->power(ip->info, 0);
96 }
97
98 void gpio_event_resume(struct early_suspend *h)
99 {
100         struct gpio_event *ip;
101         ip = container_of(h, struct gpio_event, early_suspend);
102         ip->info->power(ip->info, 1);
103         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_RESUME);
104 }
105 #endif
106
107 static int __init gpio_event_probe(struct platform_device *pdev)
108 {
109         int err;
110         struct gpio_event *ip;
111         struct input_dev *input_dev;
112         struct gpio_event_platform_data *event_info;
113
114         event_info = pdev->dev.platform_data;
115         if (event_info == NULL) {
116                 pr_err("gpio_event_probe: No pdata\n");
117                 return -ENODEV;
118         }
119         if (event_info->name == NULL ||
120            event_info->info == NULL ||
121            event_info->info_count == 0) {
122                 pr_err("gpio_event_probe: Incomplete pdata\n");
123                 return -ENODEV;
124         }
125         ip = kzalloc(sizeof(*ip) +
126                      sizeof(ip->state[0]) * event_info->info_count, GFP_KERNEL);
127         if (ip == NULL) {
128                 err = -ENOMEM;
129                 pr_err("gpio_event_probe: Failed to allocate private data\n");
130                 goto err_kp_alloc_failed;
131         }
132         platform_set_drvdata(pdev, ip);
133
134         input_dev = input_allocate_device();
135         if (input_dev == NULL) {
136                 err = -ENOMEM;
137                 pr_err("gpio_event_probe: Failed to allocate input device\n");
138                 goto err_input_dev_alloc_failed;
139         }
140         input_set_drvdata(input_dev, ip);
141         ip->input_dev = input_dev;
142         ip->info = event_info;
143         if (event_info->power) {
144 #ifdef CONFIG_HAS_EARLYSUSPEND
145                 ip->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
146                 ip->early_suspend.suspend = gpio_event_suspend;
147                 ip->early_suspend.resume = gpio_event_resume;
148                 register_early_suspend(&ip->early_suspend);
149 #endif
150                 ip->info->power(ip->info, 1);
151         }
152
153         input_dev->name = ip->info->name;
154         input_dev->event = gpio_input_event;
155
156         err = gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_INIT);
157         if (err)
158                 goto err_call_all_func_failed;
159
160         err = input_register_device(input_dev);
161         if (err) {
162                 pr_err("gpio_event_probe: Unable to register %s input device\n",
163                         input_dev->name);
164                 goto err_input_register_device_failed;
165         }
166
167         return 0;
168
169 err_input_register_device_failed:
170         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
171 err_call_all_func_failed:
172         if (event_info->power) {
173 #ifdef CONFIG_HAS_EARLYSUSPEND
174                 unregister_early_suspend(&ip->early_suspend);
175 #endif
176                 ip->info->power(ip->info, 0);
177         }
178         input_free_device(input_dev);
179 err_input_dev_alloc_failed:
180         kfree(ip);
181 err_kp_alloc_failed:
182         return err;
183 }
184
185 static int gpio_event_remove(struct platform_device *pdev)
186 {
187         struct gpio_event *ip = platform_get_drvdata(pdev);
188
189         gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
190         if (ip->info->power) {
191 #ifdef CONFIG_HAS_EARLYSUSPEND
192                 unregister_early_suspend(&ip->early_suspend);
193 #endif
194                 ip->info->power(ip->info, 0);
195         }
196         input_unregister_device(ip->input_dev);
197         kfree(ip);
198         return 0;
199 }
200
201 static struct platform_driver gpio_event_driver = {
202         .probe          = gpio_event_probe,
203         .remove         = gpio_event_remove,
204         .driver         = {
205                 .name   = GPIO_EVENT_DEV_NAME,
206         },
207 };
208
209 static int __devinit gpio_event_init(void)
210 {
211         return platform_driver_register(&gpio_event_driver);
212 }
213
214 static void __exit gpio_event_exit(void)
215 {
216         platform_driver_unregister(&gpio_event_driver);
217 }
218
219 module_init(gpio_event_init);
220 module_exit(gpio_event_exit);
221
222 MODULE_DESCRIPTION("GPIO Event Driver");
223 MODULE_LICENSE("GPL");
224