2 * $Id: joydev.c,v 1.19 2001/01/10 19:49:40 vojtech Exp $
4 * Copyright (c) 1999-2000 Vojtech Pavlik
5 * Copyright (c) 1999 Colin Van Dyke
7 * Joystick device driver for the input driver suite.
9 * Sponsored by SuSE and Intel
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Should you need to contact me, the author, you can do so either by
28 * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
29 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
33 #include <asm/system.h>
34 #include <asm/segment.h>
35 #include <linux/delay.h>
36 #include <linux/errno.h>
37 #include <linux/joystick.h>
38 #include <linux/input.h>
39 #include <linux/kernel.h>
40 #include <linux/major.h>
41 #include <linux/slab.h>
43 #include <linux/miscdevice.h>
44 #include <linux/module.h>
45 #include <linux/poll.h>
46 #include <linux/init.h>
47 #include <linux/smp_lock.h>
49 #define JOYDEV_MINOR_BASE 0
50 #define JOYDEV_MINORS 32
51 #define JOYDEV_BUFFER_SIZE 64
53 #define MSECS(t) (1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ)
59 struct input_handle handle;
60 wait_queue_head_t wait;
63 struct joydev_list *list;
64 struct js_corr corr[ABS_MAX];
65 struct JS_DATA_SAVE_TYPE glue;
68 __u16 keymap[KEY_MAX - BTN_MISC];
69 __u16 keypam[KEY_MAX - BTN_MISC];
76 struct js_event buffer[JOYDEV_BUFFER_SIZE];
80 struct fasync_struct *fasync;
81 struct joydev *joydev;
82 struct joydev_list *next;
85 static struct joydev *joydev_table[JOYDEV_MINORS];
87 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
88 MODULE_DESCRIPTION("Joystick device driver");
89 MODULE_LICENSE("GPL");
90 MODULE_SUPPORTED_DEVICE("input/js");
92 static int joydev_correct(int value, struct js_corr *corr)
98 value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 :
99 ((corr->coef[3] * (value - corr->coef[1])) >> 14)) :
100 ((corr->coef[2] * (value - corr->coef[0])) >> 14);
106 if (value < -32767) return -32767;
107 if (value > 32767) return 32767;
112 static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
114 struct joydev *joydev = handle->private;
115 struct joydev_list *list = joydev->list;
116 struct js_event event;
121 if (code < BTN_MISC || value == 2) return;
122 event.type = JS_EVENT_BUTTON;
123 event.number = joydev->keymap[code - BTN_MISC];
128 event.type = JS_EVENT_AXIS;
129 event.number = joydev->absmap[code];
130 event.value = joydev_correct(value, joydev->corr + event.number);
131 if (event.value == joydev->abs[event.number]) return;
132 joydev->abs[event.number] = event.value;
139 event.time = MSECS(jiffies);
143 memcpy(list->buffer + list->head, &event, sizeof(struct js_event));
145 if (list->startup == joydev->nabs + joydev->nkey)
146 if (list->tail == (list->head = (list->head + 1) & (JOYDEV_BUFFER_SIZE - 1)))
149 kill_fasync(&list->fasync, SIGIO, POLL_IN);
154 wake_up_interruptible(&joydev->wait);
157 static int joydev_fasync(int fd, struct file *file, int on)
160 struct joydev_list *list = file->private_data;
161 retval = fasync_helper(fd, file, on, &list->fasync);
162 return retval < 0 ? retval : 0;
165 static int joydev_release(struct inode * inode, struct file * file)
167 struct joydev_list *list = file->private_data;
168 struct joydev_list **listptr;
171 listptr = &list->joydev->list;
172 joydev_fasync(-1, file, 0);
174 while (*listptr && (*listptr != list))
175 listptr = &((*listptr)->next);
176 *listptr = (*listptr)->next;
178 if (!--list->joydev->open) {
179 if (list->joydev->exist) {
180 input_close_device(&list->joydev->handle);
182 input_unregister_minor(list->joydev->devfs);
183 joydev_table[list->joydev->minor] = NULL;
194 static int joydev_open(struct inode *inode, struct file *file)
196 struct joydev_list *list;
197 int i = MINOR(inode->i_rdev) - JOYDEV_MINOR_BASE;
199 if (i >= JOYDEV_MINORS || !joydev_table[i])
202 if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
204 memset(list, 0, sizeof(struct joydev_list));
206 list->joydev = joydev_table[i];
207 list->next = joydev_table[i]->list;
208 joydev_table[i]->list = list;
210 file->private_data = list;
212 if (!list->joydev->open++)
213 if (list->joydev->exist)
214 input_open_device(&list->joydev->handle);
219 static ssize_t joydev_write(struct file * file, const char * buffer, size_t count, loff_t *ppos)
224 static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *ppos)
226 DECLARE_WAITQUEUE(wait, current);
227 struct joydev_list *list = file->private_data;
228 struct joydev *joydev = list->joydev;
229 struct input_dev *input = joydev->handle.dev;
232 if (count < sizeof(struct js_event))
238 if (count == sizeof(struct JS_DATA_TYPE)) {
240 struct JS_DATA_TYPE data;
243 for (data.buttons = i = 0; i < 32 && i < joydev->nkey; i++)
244 data.buttons |= test_bit(joydev->keypam[i], input->key) ? (1 << i) : 0;
245 data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x;
246 data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y;
248 if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
252 list->tail = list->head;
254 return sizeof(struct JS_DATA_TYPE);
257 if (list->head == list->tail && list->startup == joydev->nabs + joydev->nkey) {
259 add_wait_queue(&list->joydev->wait, &wait);
260 current->state = TASK_INTERRUPTIBLE;
262 while (list->head == list->tail) {
264 if (!joydev->exist) {
268 if (file->f_flags & O_NONBLOCK) {
272 if (signal_pending(current)) {
273 retval = -ERESTARTSYS;
280 current->state = TASK_RUNNING;
281 remove_wait_queue(&list->joydev->wait, &wait);
287 while (list->startup < joydev->nabs + joydev->nkey && retval + sizeof(struct js_event) <= count) {
289 struct js_event event;
291 event.time = MSECS(jiffies);
293 if (list->startup < joydev->nkey) {
294 event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
295 event.number = list->startup;
296 event.value = !!test_bit(joydev->keypam[event.number], input->key);
298 event.type = JS_EVENT_AXIS | JS_EVENT_INIT;
299 event.number = list->startup - joydev->nkey;
300 event.value = joydev->abs[event.number];
303 if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
307 retval += sizeof(struct js_event);
310 while (list->head != list->tail && retval + sizeof(struct js_event) <= count) {
312 if (copy_to_user(buf + retval, list->buffer + list->tail, sizeof(struct js_event)))
315 list->tail = (list->tail + 1) & (JOYDEV_BUFFER_SIZE - 1);
316 retval += sizeof(struct js_event);
322 /* No kernel lock - fine */
323 static unsigned int joydev_poll(struct file *file, poll_table *wait)
325 struct joydev_list *list = file->private_data;
326 poll_wait(file, &list->joydev->wait, wait);
327 if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
328 return POLLIN | POLLRDNORM;
332 static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
334 struct joydev_list *list = file->private_data;
335 struct joydev *joydev = list->joydev;
336 struct input_dev *dev = joydev->handle.dev;
345 return copy_from_user(&joydev->glue.JS_CORR, (struct JS_DATA_TYPE *) arg,
346 sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
348 return copy_to_user((struct JS_DATA_TYPE *) arg, &joydev->glue.JS_CORR,
349 sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
351 return get_user(joydev->glue.JS_TIMEOUT, (int *) arg);
353 return put_user(joydev->glue.JS_TIMEOUT, (int *) arg);
354 case JS_SET_TIMELIMIT:
355 return get_user(joydev->glue.JS_TIMELIMIT, (long *) arg);
356 case JS_GET_TIMELIMIT:
357 return put_user(joydev->glue.JS_TIMELIMIT, (long *) arg);
359 return copy_from_user(&joydev->glue, (struct JS_DATA_SAVE_TYPE *) arg,
360 sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
362 return copy_to_user((struct JS_DATA_SAVE_TYPE *) arg, &joydev->glue,
363 sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
366 return put_user(JS_VERSION, (__u32 *) arg);
368 return put_user(joydev->nabs, (__u8 *) arg);
370 return put_user(joydev->nkey, (__u8 *) arg);
372 return copy_from_user(joydev->corr, (struct js_corr *) arg,
373 sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
375 return copy_to_user((struct js_corr *) arg, joydev->corr,
376 sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
378 if (copy_from_user(joydev->abspam, (__u8 *) arg, sizeof(__u8) * ABS_MAX))
380 for (i = 0; i < joydev->nabs; i++) {
381 if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
382 joydev->absmap[joydev->abspam[i]] = i;
386 return copy_to_user((__u8 *) arg, joydev->abspam,
387 sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
389 if (copy_from_user(joydev->keypam, (__u16 *) arg, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
391 for (i = 0; i < joydev->nkey; i++) {
392 if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
393 joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
397 return copy_to_user((__u16 *) arg, joydev->keypam,
398 sizeof(__u16) * (KEY_MAX - BTN_MISC)) ? -EFAULT : 0;
400 if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
402 if (!dev->name) return 0;
403 len = strlen(dev->name) + 1;
404 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
405 if (copy_to_user((char *) arg, dev->name, len)) return -EFAULT;
412 static struct file_operations joydev_fops = {
418 release: joydev_release,
420 fasync: joydev_fasync,
423 static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev)
425 struct joydev *joydev;
428 if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) &&
429 (test_bit(ABS_X, dev->absbit) || test_bit(ABS_Y, dev->absbit)) &&
430 (test_bit(BTN_TRIGGER, dev->keybit) || test_bit(BTN_A, dev->keybit)
431 || test_bit(BTN_1, dev->keybit)))) return NULL;
433 for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
434 if (minor == JOYDEV_MINORS) {
435 printk(KERN_ERR "joydev: no more free joydev devices\n");
439 if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL)))
441 memset(joydev, 0, sizeof(struct joydev));
443 init_waitqueue_head(&joydev->wait);
445 joydev->minor = minor;
446 joydev_table[minor] = joydev;
448 joydev->handle.dev = dev;
449 joydev->handle.handler = handler;
450 joydev->handle.private = joydev;
454 for (i = 0; i < ABS_MAX; i++)
455 if (test_bit(i, dev->absbit)) {
456 joydev->absmap[i] = joydev->nabs;
457 joydev->abspam[joydev->nabs] = i;
461 for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC; i++)
462 if (test_bit(i + BTN_MISC, dev->keybit)) {
463 joydev->keymap[i] = joydev->nkey;
464 joydev->keypam[joydev->nkey] = i + BTN_MISC;
468 for (i = 0; i < BTN_JOYSTICK - BTN_MISC; i++)
469 if (test_bit(i + BTN_MISC, dev->keybit)) {
470 joydev->keymap[i] = joydev->nkey;
471 joydev->keypam[joydev->nkey] = i + BTN_MISC;
475 for (i = 0; i < joydev->nabs; i++) {
476 j = joydev->abspam[i];
477 if (dev->absmax[j] == dev->absmin[j]) {
478 joydev->corr[i].type = JS_CORR_NONE;
481 joydev->corr[i].type = JS_CORR_BROKEN;
482 joydev->corr[i].prec = dev->absfuzz[j];
483 joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
484 joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + dev->absflat[j];
485 if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j])))
487 joydev->corr[i].coef[2] = (1 << 29) / t;
488 joydev->corr[i].coef[3] = (1 << 29) / t;
490 joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
493 joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
495 // printk(KERN_INFO "js%d: Joystick device for input%d\n", minor, dev->number);
497 return &joydev->handle;
500 static void joydev_disconnect(struct input_handle *handle)
502 struct joydev *joydev = handle->private;
507 input_close_device(handle);
509 input_unregister_minor(joydev->devfs);
510 joydev_table[joydev->minor] = NULL;
515 static struct input_handler joydev_handler = {
517 connect: joydev_connect,
518 disconnect: joydev_disconnect,
520 minor: JOYDEV_MINOR_BASE,
523 static int __init joydev_init(void)
525 input_register_handler(&joydev_handler);
529 static void __exit joydev_exit(void)
531 input_unregister_handler(&joydev_handler);
534 module_init(joydev_init);
535 module_exit(joydev_exit);