2 * $Id: evdev.c,v 1.10 2000/06/23 09:23:00 vojtech Exp $
4 * Copyright (c) 1999-2000 Vojtech Pavlik
6 * Event char devices, giving access to raw input device events.
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.
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.
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
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
31 #define EVDEV_MINOR_BASE 64
32 #define EVDEV_MINORS 32
33 #define EVDEV_BUFFER_SIZE 64
35 #include <linux/poll.h>
36 #include <linux/malloc.h>
37 #include <linux/module.h>
38 #include <linux/init.h>
39 #include <linux/input.h>
40 #include <linux/smp_lock.h>
46 struct input_handle handle
;
47 wait_queue_head_t wait
;
49 struct evdev_list
*list
;
53 struct input_event buffer
[EVDEV_BUFFER_SIZE
];
56 struct fasync_struct
*fasync
;
58 struct evdev_list
*next
;
61 static struct evdev
*evdev_table
[EVDEV_MINORS
] = { NULL
, /* ... */ };
63 static void evdev_event(struct input_handle
*handle
, unsigned int type
, unsigned int code
, int value
)
65 struct evdev
*evdev
= handle
->private;
66 struct evdev_list
*list
= evdev
->list
;
70 get_fast_time(&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);
76 kill_fasync(&list
->fasync
, SIGIO
, POLL_IN
);
81 wake_up_interruptible(&evdev
->wait
);
84 static int evdev_fasync(int fd
, struct file
*file
, int on
)
87 struct evdev_list
*list
= file
->private_data
;
88 retval
= fasync_helper(fd
, file
, on
, &list
->fasync
);
89 return retval
< 0 ? retval
: 0;
92 static int evdev_release(struct inode
* inode
, struct file
* file
)
94 struct evdev_list
*list
= file
->private_data
;
95 struct evdev_list
**listptr
;
98 listptr
= &list
->evdev
->list
;
99 evdev_fasync(-1, file
, 0);
101 while (*listptr
&& (*listptr
!= list
))
102 listptr
= &((*listptr
)->next
);
103 *listptr
= (*listptr
)->next
;
105 if (!--list
->evdev
->open
) {
106 if (list
->evdev
->exist
) {
107 input_close_device(&list
->evdev
->handle
);
109 input_unregister_minor(list
->evdev
->devfs
);
110 evdev_table
[list
->evdev
->minor
] = NULL
;
121 static int evdev_open(struct inode
* inode
, struct file
* file
)
123 struct evdev_list
*list
;
124 int i
= MINOR(inode
->i_rdev
) - EVDEV_MINOR_BASE
;
126 if (i
> EVDEV_MINORS
|| !evdev_table
[i
])
129 if (!(list
= kmalloc(sizeof(struct evdev_list
), GFP_KERNEL
)))
131 memset(list
, 0, sizeof(struct evdev_list
));
133 list
->evdev
= evdev_table
[i
];
134 list
->next
= evdev_table
[i
]->list
;
135 evdev_table
[i
]->list
= list
;
137 file
->private_data
= list
;
139 if (!list
->evdev
->open
++)
140 if (list
->evdev
->exist
)
141 input_open_device(&list
->evdev
->handle
);
146 static ssize_t
evdev_write(struct file
* file
, const char * buffer
, size_t count
, loff_t
*ppos
)
151 static ssize_t
evdev_read(struct file
* file
, char * buffer
, size_t count
, loff_t
*ppos
)
153 DECLARE_WAITQUEUE(wait
, current
);
154 struct evdev_list
*list
= file
->private_data
;
157 if (list
->head
== list
->tail
) {
159 add_wait_queue(&list
->evdev
->wait
, &wait
);
160 current
->state
= TASK_INTERRUPTIBLE
;
162 while (list
->head
== list
->tail
) {
164 if (file
->f_flags
& O_NONBLOCK
) {
168 if (signal_pending(current
)) {
169 retval
= -ERESTARTSYS
;
176 current
->state
= TASK_RUNNING
;
177 remove_wait_queue(&list
->evdev
->wait
, &wait
);
183 while (list
->head
!= list
->tail
&& retval
+ sizeof(struct input_event
) <= count
) {
184 if (copy_to_user(buffer
+ retval
, list
->buffer
+ list
->tail
,
185 sizeof(struct input_event
))) return -EFAULT
;
186 list
->tail
= (list
->tail
+ 1) & (EVDEV_BUFFER_SIZE
- 1);
187 retval
+= sizeof(struct input_event
);
193 /* No kernel lock - fine */
194 static unsigned int evdev_poll(struct file
*file
, poll_table
*wait
)
196 struct evdev_list
*list
= file
->private_data
;
197 poll_wait(file
, &list
->evdev
->wait
, wait
);
198 if (list
->head
!= list
->tail
)
199 return POLLIN
| POLLRDNORM
;
203 static int evdev_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
, unsigned long arg
)
205 struct evdev_list
*list
= file
->private_data
;
206 struct evdev
*evdev
= list
->evdev
;
207 struct input_dev
*dev
= evdev
->handle
.dev
;
213 return put_user(EV_VERSION
, (int *) arg
);
216 if ((retval
= put_user(dev
->idbus
, ((short *) arg
) + 0))) return retval
;
217 if ((retval
= put_user(dev
->idvendor
, ((short *) arg
) + 1))) return retval
;
218 if ((retval
= put_user(dev
->idproduct
, ((short *) arg
) + 2))) return retval
;
219 if ((retval
= put_user(dev
->idversion
, ((short *) arg
) + 3))) return retval
;
224 if (_IOC_TYPE(cmd
) != 'E' || _IOC_DIR(cmd
) != _IOC_READ
)
227 if ((_IOC_NR(cmd
) & ~EV_MAX
) == _IOC_NR(EVIOCGBIT(0,0))) {
232 switch (_IOC_NR(cmd
) & EV_MAX
) {
233 case 0: bits
= dev
->evbit
; len
= EV_MAX
; break;
234 case EV_KEY
: bits
= dev
->keybit
; len
= KEY_MAX
; break;
235 case EV_REL
: bits
= dev
->relbit
; len
= REL_MAX
; break;
236 case EV_ABS
: bits
= dev
->absbit
; len
= ABS_MAX
; break;
237 case EV_LED
: bits
= dev
->ledbit
; len
= LED_MAX
; break;
238 case EV_SND
: bits
= dev
->sndbit
; len
= SND_MAX
; break;
239 default: return -EINVAL
;
241 len
= NBITS(len
) * sizeof(long);
242 if (len
> _IOC_SIZE(cmd
)) {
243 printk(KERN_WARNING
"evdev.c: Truncating bitfield length from %d to %d\n",
244 len
, _IOC_SIZE(cmd
));
245 len
= _IOC_SIZE(cmd
);
247 return copy_to_user((char *) arg
, bits
, len
) ? -EFAULT
: len
;
250 if (_IOC_NR(cmd
) == _IOC_NR(EVIOCGNAME(0))) {
252 if (!dev
->name
) return 0;
253 len
= strlen(dev
->name
) + 1;
254 if (len
> _IOC_SIZE(cmd
)) len
= _IOC_SIZE(cmd
);
255 return copy_to_user((char *) arg
, dev
->name
, len
) ? -EFAULT
: len
;
258 if ((_IOC_NR(cmd
) & ~ABS_MAX
) == _IOC_NR(EVIOCGABS(0))) {
260 int t
= _IOC_NR(cmd
) & ABS_MAX
;
262 if ((retval
= put_user(dev
->abs
[t
], ((int *) arg
) + 0))) return retval
;
263 if ((retval
= put_user(dev
->absmin
[t
], ((int *) arg
) + 1))) return retval
;
264 if ((retval
= put_user(dev
->absmax
[t
], ((int *) arg
) + 2))) return retval
;
265 if ((retval
= put_user(dev
->absfuzz
[t
], ((int *) arg
) + 3))) return retval
;
266 if ((retval
= put_user(dev
->absflat
[t
], ((int *) arg
) + 4))) return retval
;
274 static struct file_operations evdev_fops
= {
280 release
: evdev_release
,
282 fasync
: evdev_fasync
,
285 static struct input_handle
*evdev_connect(struct input_handler
*handler
, struct input_dev
*dev
)
290 for (minor
= 0; minor
< EVDEV_MINORS
&& evdev_table
[minor
]; minor
++);
291 if (evdev_table
[minor
]) {
292 printk(KERN_ERR
"evdev: no more free evdev devices\n");
296 if (!(evdev
= kmalloc(sizeof(struct evdev
), GFP_KERNEL
)))
298 memset(evdev
, 0, sizeof(struct evdev
));
300 init_waitqueue_head(&evdev
->wait
);
302 evdev
->minor
= minor
;
303 evdev_table
[minor
] = evdev
;
305 evdev
->handle
.dev
= dev
;
306 evdev
->handle
.handler
= handler
;
307 evdev
->handle
.private = evdev
;
311 evdev
->devfs
= input_register_minor("event%d", minor
, EVDEV_MINOR_BASE
);
313 printk(KERN_INFO
"event%d: Event device for input%d\n", minor
, dev
->number
);
315 return &evdev
->handle
;
318 static void evdev_disconnect(struct input_handle
*handle
)
320 struct evdev
*evdev
= handle
->private;
325 input_close_device(handle
);
327 input_unregister_minor(evdev
->devfs
);
328 evdev_table
[evdev
->minor
] = NULL
;
333 static struct input_handler evdev_handler
= {
335 connect
: evdev_connect
,
336 disconnect
: evdev_disconnect
,
338 minor
: EVDEV_MINOR_BASE
,
341 static int __init
evdev_init(void)
343 input_register_handler(&evdev_handler
);
347 static void __exit
evdev_exit(void)
349 input_unregister_handler(&evdev_handler
);
352 module_init(evdev_init
);
353 module_exit(evdev_exit
);