1 /*
2  * $Id: evdev.c,v 1.27 2001/05/28 09:06:44 vojtech Exp $
3  *
4  *  Copyright (c) 1999-2001 Vojtech Pavlik
5  *
6  *  Event char devices, giving access to raw input device events.
7  *
8  *  Sponsored by SuSE
9  */
10 
11 /*
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25  *
26  * Should you need to contact me, the author, you can do so either by
27  * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
28  * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
29  */
30 
31 #define EVDEV_MINOR_BASE	64
32 #define EVDEV_MINORS		32
33 #define EVDEV_BUFFER_SIZE	64
34 
35 #include <linux/poll.h>
36 #include <linux/slab.h>
37 #include <linux/module.h>
38 #include <linux/init.h>
39 #include <linux/input.h>
40 #include <linux/smp_lock.h>
41 
42 struct evdev {
43 	int exist;
44 	int open;
45 	int minor;
46 	struct input_handle handle;
47 	wait_queue_head_t wait;
48 	devfs_handle_t devfs;
49 	struct evdev_list *list;
50 };
51 
52 struct evdev_list {
53 	struct input_event buffer[EVDEV_BUFFER_SIZE];
54 	int head;
55 	int tail;
56 	struct fasync_struct *fasync;
57 	struct evdev *evdev;
58 	struct evdev_list *next;
59 };
60 
61 static struct evdev *evdev_table[EVDEV_MINORS] = { NULL, /* ... */ };
62 
evdev_event(struct input_handle * handle,unsigned int type,unsigned int code,int value)63 static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
64 {
65 	struct evdev *evdev = handle->private;
66 	struct evdev_list *list = evdev->list;
67 
68 	while (list) {
69 
70 		do_gettimeofday(&list->buffer[list->head].time);
71 		list->buffer[list->head].type = type;
72 		list->buffer[list->head].code = code;
73 		list->buffer[list->head].value = value;
74 		list->head = (list->head + 1) & (EVDEV_BUFFER_SIZE - 1);
75 
76 		kill_fasync(&list->fasync, SIGIO, POLL_IN);
77 
78 		list = list->next;
79 	}
80 
81 	wake_up_interruptible(&evdev->wait);
82 }
83 
evdev_fasync(int fd,struct file * file,int on)84 static int evdev_fasync(int fd, struct file *file, int on)
85 {
86 	int retval;
87 	struct evdev_list *list = file->private_data;
88 	retval = fasync_helper(fd, file, on, &list->fasync);
89 	return retval < 0 ? retval : 0;
90 }
91 
evdev_release(struct inode * inode,struct file * file)92 static int evdev_release(struct inode * inode, struct file * file)
93 {
94 	struct evdev_list *list = file->private_data;
95 	struct evdev_list **listptr;
96 
97 	lock_kernel();
98 	listptr = &list->evdev->list;
99 	evdev_fasync(-1, file, 0);
100 
101 	while (*listptr && (*listptr != list))
102 		listptr = &((*listptr)->next);
103 	*listptr = (*listptr)->next;
104 
105 	if (!--list->evdev->open) {
106 		if (list->evdev->exist) {
107 			input_close_device(&list->evdev->handle);
108 		} else {
109 			input_unregister_minor(list->evdev->devfs);
110 			evdev_table[list->evdev->minor] = NULL;
111 			kfree(list->evdev);
112 		}
113 	}
114 
115 	kfree(list);
116 	unlock_kernel();
117 
118 	return 0;
119 }
120 
evdev_open(struct inode * inode,struct file * file)121 static int evdev_open(struct inode * inode, struct file * file)
122 {
123 	struct evdev_list *list;
124 	int i = MINOR(inode->i_rdev) - EVDEV_MINOR_BASE;
125 
126 	if (i >= EVDEV_MINORS || !evdev_table[i])
127 		return -ENODEV;
128 
129 	if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
130 		return -ENOMEM;
131 	memset(list, 0, sizeof(struct evdev_list));
132 
133 	list->evdev = evdev_table[i];
134 	list->next = evdev_table[i]->list;
135 	evdev_table[i]->list = list;
136 
137 	file->private_data = list;
138 
139 	if (!list->evdev->open++)
140 		if (list->evdev->exist)
141 			input_open_device(&list->evdev->handle);
142 
143 	return 0;
144 }
145 
evdev_write(struct file * file,const char * buffer,size_t count,loff_t * ppos)146 static ssize_t evdev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos)
147 {
148 	struct evdev_list *list = file->private_data;
149 	struct input_event event;
150 	int retval = 0;
151 
152 	while (retval < count) {
153 
154 		if (copy_from_user(&event, buffer + retval, sizeof(struct input_event)))
155 			return -EFAULT;
156 		input_event(list->evdev->handle.dev, event.type, event.code, event.value);
157 		retval += sizeof(struct input_event);
158 	}
159 
160 	return retval;
161 }
162 
evdev_read(struct file * file,char * buffer,size_t count,loff_t * ppos)163 static ssize_t evdev_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
164 {
165 	DECLARE_WAITQUEUE(wait, current);
166 	struct evdev_list *list = file->private_data;
167 	int retval = 0;
168 
169 	if (list->head == list->tail) {
170 
171 		add_wait_queue(&list->evdev->wait, &wait);
172 		current->state = TASK_INTERRUPTIBLE;
173 
174 		while (list->head == list->tail) {
175 
176 			if (!list->evdev->exist) {
177 				retval = -ENODEV;
178 				break;
179 			}
180 			if (file->f_flags & O_NONBLOCK) {
181 				retval = -EAGAIN;
182 				break;
183 			}
184 			if (signal_pending(current)) {
185 				retval = -ERESTARTSYS;
186 				break;
187 			}
188 
189 			schedule();
190 		}
191 
192 		current->state = TASK_RUNNING;
193 		remove_wait_queue(&list->evdev->wait, &wait);
194 	}
195 
196 	if (retval)
197 		return retval;
198 
199 	while (list->head != list->tail && retval + sizeof(struct input_event) <= count) {
200 		if (copy_to_user(buffer + retval, list->buffer + list->tail,
201 			 sizeof(struct input_event))) return -EFAULT;
202 		list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
203 		retval += sizeof(struct input_event);
204 	}
205 
206 	return retval;
207 }
208 
209 /* No kernel lock - fine */
evdev_poll(struct file * file,poll_table * wait)210 static unsigned int evdev_poll(struct file *file, poll_table *wait)
211 {
212 	struct evdev_list *list = file->private_data;
213 	poll_wait(file, &list->evdev->wait, wait);
214 	if (list->head != list->tail)
215 		return POLLIN | POLLRDNORM;
216 	return 0;
217 }
218 
evdev_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg)219 static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
220 {
221 	struct evdev_list *list = file->private_data;
222 	struct evdev *evdev = list->evdev;
223 	struct input_dev *dev = evdev->handle.dev;
224 	int retval;
225 
226 	if (!evdev->exist)
227 		return -ENODEV;
228 
229 	switch (cmd) {
230 
231 		case EVIOCGVERSION:
232 			return put_user(EV_VERSION, (int *) arg);
233 
234 		case EVIOCGID:
235 			if ((retval = put_user(dev->idbus,     ((short *) arg) + 0))) return retval;
236 			if ((retval = put_user(dev->idvendor,  ((short *) arg) + 1))) return retval;
237 			if ((retval = put_user(dev->idproduct, ((short *) arg) + 2))) return retval;
238 			if ((retval = put_user(dev->idversion, ((short *) arg) + 3))) return retval;
239 			return 0;
240 
241 		case EVIOCSFF:
242 			if (dev->upload_effect) {
243 				struct ff_effect effect;
244 				int err;
245 
246 				if (copy_from_user((void*)(&effect), (void*)arg, sizeof(effect))) {
247 					return -EINVAL;
248 				}
249 				err = dev->upload_effect(dev, &effect);
250 				if (put_user(effect.id, &(((struct ff_effect*)arg)->id))) {
251 					return -EINVAL;
252 				}
253 				return err;
254 			}
255 			else return -ENOSYS;
256 
257 		case EVIOCRMFF:
258 			if (dev->erase_effect) {
259 				return dev->erase_effect(dev, (int)arg);
260 			}
261 			else return -ENOSYS;
262 
263 		case EVIOCGEFFECTS:
264 			put_user(dev->ff_effects_max, (int*) arg);
265 			return 0;
266 
267 		default:
268 
269 			if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ)
270 				return -EINVAL;
271 
272 			if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
273 
274 				long *bits;
275 				int len;
276 
277 				switch (_IOC_NR(cmd) & EV_MAX) {
278 					case      0: bits = dev->evbit;  len = EV_MAX;  break;
279 					case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
280 					case EV_REL: bits = dev->relbit; len = REL_MAX; break;
281 					case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
282 					case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
283 					case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
284 					case EV_FF:  bits = dev->ffbit;  len = FF_MAX;  break;
285 					default: return -EINVAL;
286 				}
287 				len = NBITS(len) * sizeof(long);
288 				if (len > _IOC_SIZE(cmd)) {
289 					printk(KERN_WARNING "evdev.c: Truncating bitfield length from %d to %d\n",
290 						len, _IOC_SIZE(cmd));
291 					len = _IOC_SIZE(cmd);
292 				}
293 				return copy_to_user((char *) arg, bits, len) ? -EFAULT : len;
294 			}
295 
296 			if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
297 				int len;
298 				if (!dev->name) return 0;
299 				len = strlen(dev->name) + 1;
300 				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
301 				return copy_to_user((char *) arg, dev->name, len) ? -EFAULT : len;
302 			}
303 
304 			if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
305 
306 				int t = _IOC_NR(cmd) & ABS_MAX;
307 
308 				if ((retval = put_user(dev->abs[t],     ((int *) arg) + 0))) return retval;
309 				if ((retval = put_user(dev->absmin[t],  ((int *) arg) + 1))) return retval;
310 				if ((retval = put_user(dev->absmax[t],  ((int *) arg) + 2))) return retval;
311 				if ((retval = put_user(dev->absfuzz[t], ((int *) arg) + 3))) return retval;
312 				if ((retval = put_user(dev->absflat[t], ((int *) arg) + 4))) return retval;
313 
314 				return 0;
315 			}
316 	}
317 	return -EINVAL;
318 }
319 
320 static struct file_operations evdev_fops = {
321 	owner:		THIS_MODULE,
322 	read:		evdev_read,
323 	write:		evdev_write,
324 	poll:		evdev_poll,
325 	open:		evdev_open,
326 	release:	evdev_release,
327 	ioctl:		evdev_ioctl,
328 	fasync:		evdev_fasync,
329 };
330 
evdev_connect(struct input_handler * handler,struct input_dev * dev)331 static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev)
332 {
333 	struct evdev *evdev;
334 	int minor;
335 
336 	for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
337 	if (minor == EVDEV_MINORS) {
338 		printk(KERN_ERR "evdev: no more free evdev devices\n");
339 		return NULL;
340 	}
341 
342 	if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL)))
343 		return NULL;
344 	memset(evdev, 0, sizeof(struct evdev));
345 
346 	init_waitqueue_head(&evdev->wait);
347 
348 	evdev->minor = minor;
349 	evdev_table[minor] = evdev;
350 
351 	evdev->handle.dev = dev;
352 	evdev->handle.handler = handler;
353 	evdev->handle.private = evdev;
354 
355 	evdev->exist = 1;
356 
357 	evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
358 
359 //	printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number);
360 
361 	return &evdev->handle;
362 }
363 
evdev_disconnect(struct input_handle * handle)364 static void evdev_disconnect(struct input_handle *handle)
365 {
366 	struct evdev *evdev = handle->private;
367 
368 	evdev->exist = 0;
369 
370 	if (evdev->open) {
371 		input_close_device(handle);
372 		wake_up_interruptible(&evdev->wait);
373 	} else {
374 		input_unregister_minor(evdev->devfs);
375 		evdev_table[evdev->minor] = NULL;
376 		kfree(evdev);
377 	}
378 }
379 
380 static struct input_handler evdev_handler = {
381 	event:		evdev_event,
382 	connect:	evdev_connect,
383 	disconnect:	evdev_disconnect,
384 	fops:		&evdev_fops,
385 	minor:		EVDEV_MINOR_BASE,
386 };
387 
evdev_init(void)388 static int __init evdev_init(void)
389 {
390 	input_register_handler(&evdev_handler);
391 	return 0;
392 }
393 
evdev_exit(void)394 static void __exit evdev_exit(void)
395 {
396 	input_unregister_handler(&evdev_handler);
397 }
398 
399 module_init(evdev_init);
400 module_exit(evdev_exit);
401 
402 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
403 MODULE_DESCRIPTION("Event character device driver");
404 MODULE_LICENSE("GPL");
405 
406