• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 struct gpio_event {
24 	struct gpio_event_input_devs *input_devs;
25 	const struct gpio_event_platform_data *info;
26 	struct early_suspend early_suspend;
27 	void *state[0];
28 };
29 
gpio_input_event(struct input_dev * dev,unsigned int type,unsigned int code,int value)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 devnr;
35 	int ret = 0;
36 	int tmp_ret;
37 	struct gpio_event_info **ii;
38 	struct gpio_event *ip = input_get_drvdata(dev);
39 
40 	for (devnr = 0; devnr < ip->input_devs->count; devnr++)
41 		if (ip->input_devs->dev[devnr] == dev)
42 			break;
43 	if (devnr == ip->input_devs->count) {
44 		pr_err("gpio_input_event: unknown device %p\n", dev);
45 		return -EIO;
46 	}
47 
48 	for (i = 0, ii = ip->info->info; i < ip->info->info_count; i++, ii++) {
49 		if ((*ii)->event) {
50 			tmp_ret = (*ii)->event(ip->input_devs, *ii,
51 						&ip->state[i],
52 						devnr, type, code, value);
53 			if (tmp_ret)
54 				ret = tmp_ret;
55 		}
56 	}
57 	return ret;
58 }
59 
gpio_event_call_all_func(struct gpio_event * ip,int func)60 static int gpio_event_call_all_func(struct gpio_event *ip, int func)
61 {
62 	int i;
63 	int ret;
64 	struct gpio_event_info **ii;
65 
66 	if (func == GPIO_EVENT_FUNC_INIT || func == GPIO_EVENT_FUNC_RESUME) {
67 		ii = ip->info->info;
68 		for (i = 0; i < ip->info->info_count; i++, ii++) {
69 			if ((*ii)->func == NULL) {
70 				ret = -ENODEV;
71 				pr_err("gpio_event_probe: Incomplete pdata, "
72 					"no function\n");
73 				goto err_no_func;
74 			}
75 			if (func == GPIO_EVENT_FUNC_RESUME && (*ii)->no_suspend)
76 				continue;
77 			ret = (*ii)->func(ip->input_devs, *ii, &ip->state[i],
78 					  func);
79 			if (ret) {
80 				pr_err("gpio_event_probe: function failed\n");
81 				goto err_func_failed;
82 			}
83 		}
84 		return 0;
85 	}
86 
87 	ret = 0;
88 	i = ip->info->info_count;
89 	ii = ip->info->info + i;
90 	while (i > 0) {
91 		i--;
92 		ii--;
93 		if ((func & ~1) == GPIO_EVENT_FUNC_SUSPEND && (*ii)->no_suspend)
94 			continue;
95 		(*ii)->func(ip->input_devs, *ii, &ip->state[i], func & ~1);
96 err_func_failed:
97 err_no_func:
98 		;
99 	}
100 	return ret;
101 }
102 
103 #ifdef CONFIG_HAS_EARLYSUSPEND
gpio_event_suspend(struct early_suspend * h)104 void gpio_event_suspend(struct early_suspend *h)
105 {
106 	struct gpio_event *ip;
107 	ip = container_of(h, struct gpio_event, early_suspend);
108 	gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_SUSPEND);
109 	ip->info->power(ip->info, 0);
110 }
111 
gpio_event_resume(struct early_suspend * h)112 void gpio_event_resume(struct early_suspend *h)
113 {
114 	struct gpio_event *ip;
115 	ip = container_of(h, struct gpio_event, early_suspend);
116 	ip->info->power(ip->info, 1);
117 	gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_RESUME);
118 }
119 #endif
120 
gpio_event_probe(struct platform_device * pdev)121 static int __init gpio_event_probe(struct platform_device *pdev)
122 {
123 	int err;
124 	struct gpio_event *ip;
125 	struct gpio_event_platform_data *event_info;
126 	int dev_count = 1;
127 	int i;
128 	int registered = 0;
129 
130 	event_info = pdev->dev.platform_data;
131 	if (event_info == NULL) {
132 		pr_err("gpio_event_probe: No pdata\n");
133 		return -ENODEV;
134 	}
135 	if ((!event_info->name && !event_info->names[0]) ||
136 	    !event_info->info || !event_info->info_count) {
137 		pr_err("gpio_event_probe: Incomplete pdata\n");
138 		return -ENODEV;
139 	}
140 	if (!event_info->name)
141 		while (event_info->names[dev_count])
142 			dev_count++;
143 	ip = kzalloc(sizeof(*ip) +
144 		     sizeof(ip->state[0]) * event_info->info_count +
145 		     sizeof(*ip->input_devs) +
146 		     sizeof(ip->input_devs->dev[0]) * dev_count, GFP_KERNEL);
147 	if (ip == NULL) {
148 		err = -ENOMEM;
149 		pr_err("gpio_event_probe: Failed to allocate private data\n");
150 		goto err_kp_alloc_failed;
151 	}
152 	ip->input_devs = (void*)&ip->state[event_info->info_count];
153 	platform_set_drvdata(pdev, ip);
154 
155 	for (i = 0; i < dev_count; i++) {
156 		struct input_dev *input_dev = input_allocate_device();
157 		if (input_dev == NULL) {
158 			err = -ENOMEM;
159 			pr_err("gpio_event_probe: "
160 				"Failed to allocate input device\n");
161 			goto err_input_dev_alloc_failed;
162 		}
163 		input_set_drvdata(input_dev, ip);
164 		input_dev->name = event_info->name ?
165 					event_info->name : event_info->names[i];
166 		input_dev->event = gpio_input_event;
167 		ip->input_devs->dev[i] = input_dev;
168 	}
169 	ip->input_devs->count = dev_count;
170 	ip->info = event_info;
171 	if (event_info->power) {
172 #ifdef CONFIG_HAS_EARLYSUSPEND
173 		ip->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
174 		ip->early_suspend.suspend = gpio_event_suspend;
175 		ip->early_suspend.resume = gpio_event_resume;
176 		register_early_suspend(&ip->early_suspend);
177 #endif
178 		ip->info->power(ip->info, 1);
179 	}
180 
181 	err = gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_INIT);
182 	if (err)
183 		goto err_call_all_func_failed;
184 
185 	for (i = 0; i < dev_count; i++) {
186 		err = input_register_device(ip->input_devs->dev[i]);
187 		if (err) {
188 			pr_err("gpio_event_probe: Unable to register %s "
189 				"input device\n", ip->input_devs->dev[i]->name);
190 			goto err_input_register_device_failed;
191 		}
192 		registered++;
193 	}
194 
195 	return 0;
196 
197 err_input_register_device_failed:
198 	gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
199 err_call_all_func_failed:
200 	if (event_info->power) {
201 #ifdef CONFIG_HAS_EARLYSUSPEND
202 		unregister_early_suspend(&ip->early_suspend);
203 #endif
204 		ip->info->power(ip->info, 0);
205 	}
206 	for (i = 0; i < registered; i++)
207 		input_unregister_device(ip->input_devs->dev[i]);
208 	for (i = dev_count - 1; i >= registered; i--) {
209 		input_free_device(ip->input_devs->dev[i]);
210 err_input_dev_alloc_failed:
211 		;
212 	}
213 	kfree(ip);
214 err_kp_alloc_failed:
215 	return err;
216 }
217 
gpio_event_remove(struct platform_device * pdev)218 static int gpio_event_remove(struct platform_device *pdev)
219 {
220 	struct gpio_event *ip = platform_get_drvdata(pdev);
221 	int i;
222 
223 	gpio_event_call_all_func(ip, GPIO_EVENT_FUNC_UNINIT);
224 	if (ip->info->power) {
225 #ifdef CONFIG_HAS_EARLYSUSPEND
226 		unregister_early_suspend(&ip->early_suspend);
227 #endif
228 		ip->info->power(ip->info, 0);
229 	}
230 	for (i = 0; i < ip->input_devs->count; i++)
231 		input_unregister_device(ip->input_devs->dev[i]);
232 	kfree(ip);
233 	return 0;
234 }
235 
236 static struct platform_driver gpio_event_driver = {
237 	.probe		= gpio_event_probe,
238 	.remove		= gpio_event_remove,
239 	.driver		= {
240 		.name	= GPIO_EVENT_DEV_NAME,
241 	},
242 };
243 
gpio_event_init(void)244 static int __devinit gpio_event_init(void)
245 {
246 	return platform_driver_register(&gpio_event_driver);
247 }
248 
gpio_event_exit(void)249 static void __exit gpio_event_exit(void)
250 {
251 	platform_driver_unregister(&gpio_event_driver);
252 }
253 
254 module_init(gpio_event_init);
255 module_exit(gpio_event_exit);
256 
257 MODULE_DESCRIPTION("GPIO Event Driver");
258 MODULE_LICENSE("GPL");
259 
260