* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / char / joystick / joystick.c
blob941f1795de69fe0ba9f26c9d58e0e7e4026ba1f7
1 /*
2 * joystick.c Version 1.2
4 * Copyright (c) 1996-1998 Vojtech Pavlik
5 */
7 /*
8 * This is the main joystick driver for Linux. It doesn't support any
9 * devices directly, rather is lets you use sub-modules to do that job. See
10 * Documentation/joystick.txt for more info.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Should you need to contact me, the author, you can do so either by
29 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
30 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
33 #include <asm/io.h>
34 #include <asm/system.h>
35 #include <asm/segment.h>
36 #include <linux/config.h>
37 #include <linux/delay.h>
38 #include <linux/errno.h>
39 #include <linux/joystick.h>
40 #include <linux/kernel.h>
41 #include <linux/major.h>
42 #include <linux/malloc.h>
43 #include <linux/mm.h>
44 #include <linux/module.h>
45 #include <linux/version.h>
46 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
47 #include <linux/spinlock.h>
48 #include <linux/poll.h>
49 #endif
52 * Configurable parameters.
55 #define JS_REFRESH_TIME HZ/50 /* Time between two reads of joysticks (20ms) */
58 * Buffer macros.
61 #define ROT(A,B,C) ((((A)<(C))&&(((B)>(A))&&((B)<(C))))||(((A)>(C))&&(((B)>(A))||((B)<(C)))))
62 #define GOF(X) (((X)==JS_BUFF_SIZE-1)?0:(X)+1)
63 #define GOB(X) ((X)?(X)-1:JS_BUFF_SIZE-1)
64 #define DIFF(X,Y) ((X)>(Y)?(X)-(Y):(Y)-(X))
67 * Global variables.
70 static struct JS_DATA_SAVE_TYPE js_comp_glue;
71 static struct js_port *js_port = NULL;
72 static struct js_dev *js_dev = NULL;
73 static struct timer_list js_timer;
74 spinlock_t js_lock = SPIN_LOCK_UNLOCKED;
75 static int js_use_count = 0;
78 * Exported variables.
81 unsigned int js_time_speed = 0;
82 js_time_func js_get_time;
83 js_delta_func js_delta;
85 unsigned int js_time_speed_a = 0;
86 js_time_func js_get_time_a;
87 js_delta_func js_delta_a;
90 * Module info.
93 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
94 MODULE_SUPPORTED_DEVICE("js");
97 * js_get_time_*() are different functions to get current time.
98 * js_delta_*() are functions to compute time difference.
101 #ifdef __i386__
103 static unsigned int js_get_time_rdtsc(void)
105 unsigned int x;
106 __asm__ __volatile__ ( "rdtsc" : "=A" (x) );
107 return x;
110 static unsigned int js_get_time_pit(void)
112 unsigned long flags;
113 unsigned int x;
115 __save_flags(flags);
116 __cli();
117 outb(0, 0x43);
118 x = inb(0x40);
119 x |= inb(0x40) << 8;
120 __restore_flags(flags);
122 return x;
125 static int js_delta_pit(unsigned int x, unsigned int y)
127 return y - x + ( y < x ? 1193180L / HZ : 0 );
130 static unsigned int js_get_time_counter(void)
132 static int time_counter = 0;
133 return time_counter++;
136 #else
137 #ifdef __alpha__
139 static unsigned int js_get_time_rpcc(void)
141 unsigned int x;
142 __asm__ __volatile__ ( "rpcc %0" : "=r" (x) );
143 return x;
146 #else
148 #ifndef MODULE
149 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
150 static unsigned int js_get_time_system(void)
152 static struct timeval js_tv;
153 get_fast_time(&js_tv);
154 return js_tv.tv_sec * 1000000L + js_tv.tv_usec;
156 #endif
157 #endif
159 #endif
160 #endif
162 static int js_delta_normal(unsigned int x, unsigned int y)
164 return x - y;
168 * js_calibrate_time() calibrates a given timer.
171 static int __init js_calibrate_time(js_time_func get_time, js_delta_func delta)
173 unsigned int t1, t2, t3;
174 unsigned long flags;
176 __save_flags(flags);
177 __cli();
178 t1 = get_time();
179 udelay(1000);
180 t2 = get_time();
181 t3 = get_time();
182 __restore_flags(flags);
184 return delta(t2, t1) - delta(t3, t2);
188 * js_calibrate_time_counter() calibrates the counter timer, which can't
189 * be calibrated using the above function.
192 #ifdef __i386__
194 static int __init js_calibrate_time_counter(void)
196 unsigned int i, j, t1, t2, t3;
198 j = jiffies; do { inb(0x201); t1 = js_get_time_counter(); } while (j == jiffies);
199 j = jiffies; do { inb(0x201); t2 = js_get_time_counter(); } while (j == jiffies);
201 j = (t2 - t1) * HZ / 1000;
203 t1 = js_get_time_pit();
204 for (i = 0; i < 1000; i++) {
205 inb(0x201);
206 js_get_time_counter();
208 t2 = js_get_time_pit();
209 t3 = js_get_time_pit();
211 i = 1193180L / (js_delta_pit(t2, t1) - js_delta_pit(t3, t2));
213 if (DIFF(i,j) > 5)
214 printk(KERN_WARNING "js: Counter timer calibration unsure,"
215 " pass1 (0.%d MHz) and pass2 (0.%d MHz) differ.\n", j, i);
217 return (i + j) >> 1;
220 #endif
223 * js_setup_time chooses the best available timers
224 * on the system and calibrates them.
227 static int __init js_setup_time(void)
229 int t;
230 char *name, *name_a;
232 name = "";
233 name_a = "";
234 js_time_speed = 0;
235 js_time_speed_a = 0;
237 #ifdef __i386__
239 t = js_calibrate_time(js_get_time_pit, js_delta_pit);
241 if (DIFF(t, 1193) > 5)
242 printk(KERN_WARNING "js: Measured PIT speed is %d.%03d MHz, but should be 1.193 MHz.\n"
243 KERN_WARNING "js: This is probably caused by wrong BogoMIPS value. It is: %ld, should be: %ld.\n",
244 t / 1000, t % 1000, loops_per_sec / 500000, loops_per_sec / (t * 500000 / 1193));
246 if (JS_HAS_RDTSC && (t = js_calibrate_time(js_get_time_rdtsc, js_delta_normal)) > 0) {
248 js_time_speed_a = t;
249 js_get_time_a = js_get_time_rdtsc;
250 js_delta_a = js_delta_normal;
251 js_time_speed = t;
252 js_get_time = js_get_time_rdtsc;
253 js_delta = js_delta_normal;
254 name = "RDTSC";
256 } else {
258 js_time_speed_a = t;
259 js_get_time_a = js_get_time_pit;
260 js_delta_a = js_delta_pit;
261 name_a = "PIT";
263 t = js_calibrate_time_counter();
265 js_time_speed = t;
266 js_get_time = js_get_time_counter;
267 js_delta = js_delta_normal;
268 name = "counter";
272 #else
273 #ifdef __alpha__
275 t = js_calibrate_time(js_get_time_rpcc, js_delta_normal);
277 js_time_speed_a = t;
278 js_get_time_a = js_get_time_rpcc;
279 js_delta_a = js_delta_normal;
280 js_time_speed = t;
281 js_get_time = js_get_time_rpcc;
282 js_delta = js_delta_normal;
283 name = "RPCC";
285 #else
287 #ifndef MODULE
288 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
289 t = js_calibrate_time(js_get_time_system, js_delta_normal);
291 js_time_speed_a = t;
292 js_get_time_a = js_get_time_system;
293 js_delta_a = js_delta_normal;
294 js_time_speed = t;
295 js_get_time = js_get_time_system;
296 js_delta = js_delta_normal;
297 name = "system";
298 #endif
299 #endif
301 #endif
302 #endif
304 printk(KERN_INFO "js: Version %d.%d.%d ",
305 JS_VERSION >> 16 & 0xff, JS_VERSION >> 8 & 0xff, JS_VERSION & 0xff);
307 if (js_time_speed_a <= 0 || js_time_speed <= 0) {
308 printk("\n");
309 return -1;
312 printk("using ");
314 if (js_time_speed > 10000) {
315 t = js_time_speed / 1000 + (js_time_speed % 1000 >= 500);
316 printk("%d MHz ", t);
317 } else {
318 t = js_time_speed / 10 + (js_time_speed % 10 >= 5);
319 printk("%d.%02d MHz ", t / 100, t % 100);
322 if (js_get_time_a != js_get_time) {
323 t = js_time_speed_a / 10 + (js_time_speed_a % 10 >= 5);
324 printk("%s timer and %d.%02d MHz %s timer.\n",
325 name, t / 100, t % 100, name_a);
326 } else {
327 printk("%s timer.\n", name);
330 return 0;
335 * js_correct() performs correction of raw joystick data.
338 static int js_correct(int value, struct js_corr *corr)
340 switch (corr->type) {
341 case JS_CORR_NONE:
342 break;
343 case JS_CORR_BROKEN:
344 value = value > corr->coef[0] ? (value < corr->coef[1] ? 0 :
345 ((corr->coef[3] * (value - corr->coef[1])) >> 14)) :
346 ((corr->coef[2] * (value - corr->coef[0])) >> 14);
347 break;
349 default:
350 return 0;
353 if (value < -32767) return -32767;
354 if (value > 32767) return 32767;
356 return value;
360 * js_button() returns value of button number i.
363 static inline int js_button(int *buttons, int i)
365 return (buttons[i >> 5] >> (i & 0x1f)) & 1;
370 * js_add_event() adds an event to the buffer. This requires additional
371 * queue post-processing done by js_sync_buff.
374 static void js_add_event(struct js_dev *jd, __u32 time, __u8 type, __u8 number, __s16 value)
376 jd->buff[jd->ahead].time = time;
377 jd->buff[jd->ahead].type = type;
378 jd->buff[jd->ahead].number = number;
379 jd->buff[jd->ahead].value = value;
380 if (++jd->ahead == JS_BUFF_SIZE) jd->ahead = 0;
384 * js_flush_data() does the same as js_process_data, except for that it doesn't
385 * generate any events - it just copies the data from new to cur.
388 static void js_flush_data(struct js_dev *jd)
390 int i;
392 for (i = 0; i < ((jd->num_buttons - 1) >> 5) + 1; i++)
393 jd->cur.buttons[i] = jd->new.buttons[i];
394 for (i = 0; i < jd->num_axes; i++)
395 jd->cur.axes[i] = jd->new.axes[i];
399 * js_process_data() finds changes in button states and axis positions and adds
400 * them as events to the buffer.
403 static void js_process_data(struct js_dev *jd)
405 int i, t;
407 for (i = 0; i < jd->num_buttons; i++)
408 if ((t = js_button(jd->new.buttons, i)) != js_button(jd->cur.buttons, i)) {
409 js_add_event(jd, jiffies, JS_EVENT_BUTTON, i, t);
410 jd->cur.buttons[i >> 5] ^= (1 << (i & 0x1f));
413 for (i = 0; i < jd->num_axes; i++) {
414 t = js_correct(jd->new.axes[i], &jd->corr[i]);
415 if (((jd->corr[i].prec == -1) && t) ||
416 ((DIFF(jd->new.axes[i], jd->cur.axes[i]) > jd->corr[i].prec) &&
417 (t != js_correct(jd->cur.axes[i], &jd->corr[i])))) {
418 js_add_event(jd, jiffies, JS_EVENT_AXIS, i, t);
419 jd->cur.axes[i] = jd->new.axes[i];
425 * js_sync_buff() checks for all overflows caused by recent additions to the buffer.
426 * These happen only if some process is reading the data too slowly. It
427 * wakes up any process waiting for data.
430 static void js_sync_buff(struct js_dev *jd)
432 struct js_list *curl = jd->list;
434 if (jd->bhead != jd->ahead) {
435 if(ROT(jd->bhead, jd->tail, jd->ahead) || (jd->tail == jd->bhead)) {
436 while (curl) {
437 if (ROT(jd->bhead, curl->tail, jd->ahead) || (curl->tail == jd->bhead)) {
438 curl->tail = jd->ahead;
439 curl->startup = 0;
441 curl = curl->next;
443 jd->tail = jd->ahead;
445 jd->bhead = jd->ahead;
446 wake_up_interruptible(&jd->wait);
451 * js_do_timer() acts as an interrupt replacement. It reads the data
452 * from all ports and then generates events for all devices.
455 static void js_do_timer(unsigned long data)
457 struct js_port *curp = js_port;
458 struct js_dev *curd = js_dev;
459 unsigned long flags;
461 while (curp != NULL) {
462 curp->read(curp->info, curp->axes, curp->buttons);
463 curp = curp->next;
466 spin_lock_irqsave(&js_lock, flags);
468 while (curd != NULL) {
469 if (data) {
470 js_process_data(curd);
471 js_sync_buff(curd);
472 } else {
473 js_flush_data(curd);
475 curd = curd->next;
478 spin_unlock_irqrestore(&js_lock, flags);
480 js_timer.expires = jiffies + JS_REFRESH_TIME;
481 add_timer(&js_timer);
485 * js_read() copies one or more entries from jsd[].buff to user
486 * space.
489 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
490 static ssize_t js_read(struct file *file, char *buf, size_t count, loff_t *ppos)
491 #else
492 static int js_read(struct inode *inode, struct file *file, char *buf, int count)
493 #endif
495 DECLARE_WAITQUEUE(wait, current);
496 struct js_event *buff = (void *) buf;
497 struct js_list *curl;
498 struct js_dev *jd;
499 unsigned long blocks = count / sizeof(struct js_event);
500 int written = 0;
501 int new_tail, orig_tail;
502 int retval = 0;
503 unsigned long flags;
505 curl = file->private_data;
506 jd = curl->dev;
507 orig_tail = curl->tail;
510 * Check user data.
513 if (!blocks)
514 return -EINVAL;
517 * Lock it.
520 spin_lock_irqsave(&js_lock, flags);
523 * Handle (non)blocking i/o.
525 if (count != sizeof(struct JS_DATA_TYPE)) {
527 if (GOF(curl->tail) == jd->bhead && curl->startup == jd->num_axes + jd->num_buttons) {
529 __set_current_state(TASK_INTERRUPTIBLE);
530 add_wait_queue(&jd->wait, &wait);
532 while (GOF(curl->tail) == jd->bhead) {
534 if (file->f_flags & O_NONBLOCK) {
535 retval = -EAGAIN;
536 break;
538 if (signal_pending(current)) {
539 retval = -ERESTARTSYS;
540 break;
543 spin_unlock_irqrestore(&js_lock, flags);
544 schedule();
545 spin_lock_irqsave(&js_lock, flags);
549 current->state = TASK_RUNNING;
550 remove_wait_queue(&jd->wait, &wait);
553 if (retval) {
554 spin_unlock_irqrestore(&js_lock, flags);
555 return retval;
559 * Initial state.
562 while (curl->startup < jd->num_axes + jd->num_buttons && written < blocks && !retval) {
564 struct js_event tmpevent;
566 if (curl->startup < jd->num_buttons) {
567 tmpevent.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
568 tmpevent.value = js_button(jd->cur.buttons, curl->startup);
569 tmpevent.number = curl->startup;
570 } else {
571 tmpevent.type = JS_EVENT_AXIS | JS_EVENT_INIT;
572 tmpevent.value = js_correct(jd->cur.axes[curl->startup - jd->num_buttons],
573 &jd->corr[curl->startup - jd->num_buttons]);
574 tmpevent.number = curl->startup - jd->num_buttons;
577 tmpevent.time = jiffies * (1000/HZ);
579 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
580 if (copy_to_user(&buff[written], &tmpevent, sizeof(struct js_event)))
581 retval = -EFAULT;
582 #else
583 if (!(retval = verify_area(VERIFY_WRITE, &buff[written], sizeof(struct js_event))))
584 memcpy_tofs(&buff[written], &tmpevent, sizeof(struct js_event));
585 #endif
587 curl->startup++;
588 written++;
592 * Buffer data.
595 while ((jd->bhead != (new_tail = GOF(curl->tail))) && (written < blocks) && !retval) {
597 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
598 if (copy_to_user(&buff[written], &jd->buff[new_tail], sizeof(struct js_event)))
599 retval = -EFAULT;
600 if (put_user((__u32)(jd->buff[new_tail].time * (1000/HZ)), &buff[written].time))
601 retval = -EFAULT;
602 #else
603 if (!(retval = verify_area(VERIFY_WRITE, &buff[written], sizeof(struct js_event)))) {
604 memcpy_tofs(&buff[written], &jd->buff[new_tail], sizeof(struct js_event));
605 put_user((__u32)(jd->buff[new_tail].time * (1000/HZ)), &buff[written].time);
607 #endif
608 curl->tail = new_tail;
609 written++;
613 else
616 * Handle version 0.x compatibility.
620 struct JS_DATA_TYPE data;
622 data.buttons = jd->new.buttons[0];
623 data.x = jd->num_axes < 1 ? 0 :
624 ((js_correct(jd->new.axes[0], &jd->corr[0]) / 256) + 128) >> js_comp_glue.JS_CORR.x;
625 data.y = jd->num_axes < 2 ? 0 :
626 ((js_correct(jd->new.axes[1], &jd->corr[1]) / 256) + 128) >> js_comp_glue.JS_CORR.y;
628 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
629 retval = copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
630 #else
631 if (!(retval = verify_area(VERIFY_WRITE, buf, sizeof(struct JS_DATA_TYPE)))) {
632 memcpy_tofs(buf, &data, sizeof(struct JS_DATA_TYPE));
634 #endif
636 curl->startup = 0;
637 curl->tail = GOB(jd->bhead);
638 if (!retval) retval = sizeof(struct JS_DATA_TYPE);
642 * Check main tail and move it.
645 if (orig_tail == jd->tail) {
646 new_tail = curl->tail;
647 curl = jd->list;
648 while (curl != NULL && curl->tail != jd->tail) {
649 if (ROT(jd->bhead, new_tail, curl->tail) ||
650 (jd->bhead == curl->tail)) new_tail = curl->tail;
651 curl = curl->next;
653 if (curl == NULL) jd->tail = new_tail;
656 spin_unlock_irqrestore(&js_lock, flags);
658 return retval ? retval : written * sizeof(struct js_event);
662 * js_poll() does select() support.
665 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
667 static unsigned int js_poll(struct file *file, poll_table *wait)
669 struct js_list *curl = file->private_data;
670 unsigned long flags;
671 int retval = 0;
672 poll_wait(file, &curl->dev->wait, wait);
673 spin_lock_irqsave(&js_lock, flags);
674 if (GOF(curl->tail) != curl->dev->bhead ||
675 curl->startup < curl->dev->num_axes + curl->dev->num_buttons) retval = POLLIN | POLLRDNORM;
676 spin_unlock_irqrestore(&js_lock, flags);
677 return retval;
680 #else
682 static int js_select(struct inode *inode, struct file *file, int sel_type, select_table *wait)
684 struct js_list *curl = file->private_data;
685 if (sel_type == SEL_IN) {
686 if (GOF(curl->tail) != curl->dev->bhead) return 1;
687 select_wait(&curl->dev->wait, wait);
689 return 0;
692 #endif
695 * js_ioctl handles misc ioctl calls.
698 static int js_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
700 struct js_list *curl;
701 struct js_dev *jd;
702 int len;
704 curl = file->private_data;
705 jd = curl->dev;
707 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
709 switch (cmd) {
712 * 0.x compatibility
715 case JS_SET_CAL:
716 return copy_from_user(&js_comp_glue.JS_CORR, (struct JS_DATA_TYPE *) arg,
717 sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
718 case JS_GET_CAL:
719 return copy_to_user((struct JS_DATA_TYPE *) arg, &js_comp_glue.JS_CORR,
720 sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;
721 case JS_SET_TIMEOUT:
722 return get_user(js_comp_glue.JS_TIMEOUT, (int *) arg);
723 case JS_GET_TIMEOUT:
724 return put_user(js_comp_glue.JS_TIMEOUT, (int *) arg);
725 case JS_SET_TIMELIMIT:
726 return get_user(js_comp_glue.JS_TIMELIMIT, (long *) arg);
727 case JS_GET_TIMELIMIT:
728 return put_user(js_comp_glue.JS_TIMELIMIT, (long *) arg);
729 case JS_SET_ALL:
730 return copy_from_user(&js_comp_glue, (struct JS_DATA_SAVE_TYPE *) arg,
731 sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
732 case JS_GET_ALL:
733 return copy_to_user((struct JS_DATA_SAVE_TYPE *) arg, &js_comp_glue,
734 sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;
737 * 1.x ioctl calls
740 case JSIOCGVERSION:
741 return put_user(JS_VERSION, (__u32 *) arg);
742 case JSIOCGAXES:
743 return put_user(jd->num_axes, (__u8 *) arg);
744 case JSIOCGBUTTONS:
745 return put_user(jd->num_buttons, (__u8 *) arg);
746 case JSIOCSCORR:
747 return copy_from_user(jd->corr, (struct js_corr *) arg,
748 sizeof(struct js_corr) * jd->num_axes) ? -EFAULT : 0;
749 case JSIOCGCORR:
750 return copy_to_user((struct js_corr *) arg, jd->corr,
751 sizeof(struct js_corr) * jd->num_axes) ? -EFAULT : 0;
752 default:
753 if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
754 len = strlen(jd->name) + 1;
755 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
756 if (copy_to_user((char *) arg, jd->name, len)) return -EFAULT;
757 return len;
761 #else
763 switch (cmd) {
766 * 0.x compatibility
769 case JS_SET_CAL:
770 if (verify_area(VERIFY_READ, (struct JS_DATA_TYPE *) arg,
771 sizeof(struct JS_DATA_TYPE))) return -EFAULT;
772 memcpy_fromfs(&js_comp_glue.JS_CORR, (struct JS_DATA_SAVE_TYPE *) arg,
773 sizeof(struct JS_DATA_TYPE));
774 return 0;
775 case JS_GET_CAL:
776 if (verify_area(VERIFY_WRITE, (struct JS_DATA_TYPE *) arg,
777 sizeof(struct JS_DATA_TYPE))) return -EFAULT;
778 memcpy_tofs((struct JS_DATA_SAVE_TYPE *) arg, &js_comp_glue.JS_CORR,
779 sizeof(struct JS_DATA_TYPE));
780 return 0;
781 case JS_SET_TIMEOUT:
782 if (verify_area(VERIFY_READ, (int *) arg, sizeof(int))) return -EFAULT;
783 js_comp_glue.JS_TIMEOUT = get_user((int *) arg);
784 return 0;
785 case JS_GET_TIMEOUT:
786 if (verify_area(VERIFY_WRITE, (int *) arg, sizeof(int))) return -EFAULT;
787 put_user(js_comp_glue.JS_TIMEOUT, (int *) arg);
788 return 0;
789 case JS_SET_TIMELIMIT:
790 if (verify_area(VERIFY_READ, (long *) arg, sizeof(long))) return -EFAULT;
791 js_comp_glue.JS_TIMELIMIT = get_user((long *) arg);
792 return 0;
793 case JS_GET_TIMELIMIT:
794 if (verify_area(VERIFY_WRITE, (long *) arg, sizeof(long))) return -EFAULT;
795 put_user(js_comp_glue.JS_TIMELIMIT, (long *) arg);
796 return 0;
797 case JS_SET_ALL:
798 if (verify_area(VERIFY_READ, (struct JS_DATA_SAVE_TYPE *) arg,
799 sizeof(struct JS_DATA_SAVE_TYPE))) return -EFAULT;
800 memcpy_fromfs(&js_comp_glue, (struct JS_DATA_SAVE_TYPE *) arg,
801 sizeof(struct JS_DATA_SAVE_TYPE));
802 return 0;
803 case JS_GET_ALL:
804 if (verify_area(VERIFY_WRITE, (struct JS_DATA_SAVE_TYPE *) arg,
805 sizeof(struct JS_DATA_SAVE_TYPE))) return -EFAULT;
806 memcpy_tofs((struct JS_DATA_SAVE_TYPE *) arg, &js_comp_glue,
807 sizeof(struct JS_DATA_SAVE_TYPE));
808 return 0;
811 * 1.x ioctl calls
814 case JSIOCGVERSION:
815 if (verify_area(VERIFY_WRITE, (__u32 *) arg, sizeof(__u32))) return -EFAULT;
816 put_user(JS_VERSION, (__u32 *) arg);
817 return 0;
818 case JSIOCGAXES:
819 if (verify_area(VERIFY_WRITE, (__u8 *) arg, sizeof(__u8))) return -EFAULT;
820 put_user(jd->num_axes, (__u8 *) arg);
821 return 0;
822 case JSIOCGBUTTONS:
823 if (verify_area(VERIFY_WRITE, (__u8 *) arg, sizeof(__u8))) return -EFAULT;
824 put_user(jd->num_buttons, (__u8 *) arg);
825 return 0;
826 case JSIOCSCORR:
827 if (verify_area(VERIFY_READ, (struct js_corr *) arg,
828 sizeof(struct js_corr) * jd->num_axes)) return -EFAULT;
829 memcpy_fromfs(jd->corr, (struct js_corr *) arg,
830 sizeof(struct js_corr) * jd->num_axes);
831 return 0;
832 case JSIOCGCORR:
833 if (verify_area(VERIFY_WRITE, (struct js_corr *) arg,
834 sizeof(struct js_corr) * jd->num_axes)) return -EFAULT;
835 memcpy_tofs((struct js_corr *) arg,
836 jd->corr, sizeof(struct js_corr) * jd->num_axes);
837 return 0;
838 default:
839 if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
840 len = strlen(jd->name) + 1;
841 if (verify_area(VERIFY_WRITE, (char *) arg, len)) return -EFAULT;
842 if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
843 memcpy_tofs((char *) arg, jd->name, len);
844 return len;
848 #endif
850 return -EINVAL;
854 * js_open() performs necessary initialization and adds
855 * an entry to the linked list.
858 static int js_open(struct inode *inode, struct file *file)
860 struct js_list *curl, *new;
861 struct js_dev *jd = js_dev;
862 int i = MINOR(inode->i_rdev);
863 unsigned long flags;
864 int result;
866 if (MAJOR(inode->i_rdev) != JOYSTICK_MAJOR)
867 return -EINVAL;
869 spin_lock_irqsave(&js_lock, flags);
871 while (i > 0 && jd != NULL) {
872 jd = jd->next;
873 i--;
876 spin_unlock_irqrestore(&js_lock, flags);
878 if (jd == NULL) return -ENODEV;
880 if ((result = jd->open(jd))) return result;
882 MOD_INC_USE_COUNT;
883 if (!js_use_count++) js_do_timer(0);
885 if ((new = kmalloc(sizeof(struct js_list), GFP_KERNEL)) != NULL) {
887 spin_lock_irqsave(&js_lock, flags);
889 curl = jd->list;
891 jd->list = new;
892 jd->list->next = curl;
893 jd->list->dev = jd;
894 jd->list->startup = 0;
895 jd->list->tail = GOB(jd->bhead);
896 file->private_data = jd->list;
898 spin_unlock_irqrestore(&js_lock, flags);
900 } else {
901 result = -ENOMEM;
904 return result;
908 * js_release() removes an entry from list and deallocates memory
909 * used by it.
912 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
913 static int js_release(struct inode *inode, struct file *file)
914 #else
915 static void js_release(struct inode *inode, struct file *file)
916 #endif
918 struct js_list *curl = file->private_data;
919 struct js_dev *jd = curl->dev;
920 struct js_list **curp = &jd->list;
921 int new_tail;
922 unsigned long flags;
924 spin_lock_irqsave(&js_lock, flags);
926 while (*curp && (*curp != curl)) curp = &((*curp)->next);
927 *curp = (*curp)->next;
929 if (jd->list != NULL)
930 if (curl->tail == jd->tail) {
931 curl = jd->list;
932 new_tail = curl->tail;
933 while (curl != NULL && curl->tail != jd->tail) {
934 if (ROT(jd->bhead, new_tail, curl->tail) ||
935 (jd->bhead == curl->tail)) new_tail = curl->tail;
936 curl = curl->next;
938 if (!curl) jd->tail = new_tail;
941 spin_unlock_irqrestore(&js_lock, flags);
943 kfree(file->private_data);
945 if (!--js_use_count) del_timer(&js_timer);
946 MOD_DEC_USE_COUNT;
948 jd->close(jd);
950 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
951 return 0;
952 #endif
956 * js_dump_mem() dumps all data structures in memory.
957 * It's used for debugging only.
960 #if 0
961 static void js_dump_mem(void)
964 struct js_port *curp = js_port;
965 struct js_dev *curd = js_dev;
966 int i;
968 printk(",--- Dumping Devices:\n");
969 printk("| js_dev = %x\n", (int) js_dev);
971 while (curd != NULL) {
972 printk("| %s-device %x, next %x axes %d, buttons %d, port %x - %#x\n",
973 curd->next ? "|":"`",
974 (int) curd, (int) curd->next, curd->num_axes, curd->num_buttons, (int) curd->port, curd->port->io);
975 curd = curd->next;
978 printk(">--- Dumping ports:\n");
979 printk("| js_port = %x\n", (int) js_port);
981 while (curp != NULL) {
982 printk("| %s-port %x, next %x, io %#x, devices %d\n",
983 curp->next ? "|":"`",
984 (int) curp, (int) curp->next, curp->io, curp->ndevs);
985 for (i = 0; i < curp->ndevs; i++) {
986 curd = curp->devs[i];
987 if (curd)
988 printk("| %s %s-device %x, next %x axes %d, buttons %d, port %x\n",
989 curp->next ? "|":" ", (i < curp->ndevs-1) ? "|":"`",
990 (int) curd, (int) curd->next, curd->num_axes, curd->num_buttons, (int) curd->port);
991 else
992 printk("| %s %s-device %x, not there\n",
993 curp->next ? "|":" ", (i < curp->ndevs-1) ? "|":"`", (int) curd);
996 curp = curp->next;
999 printk("`--- Done\n");
1001 #endif
1004 struct js_port *js_register_port(struct js_port *port,
1005 void *info, int devs, int infos, js_read_func read)
1007 struct js_port **ptrp = &js_port;
1008 struct js_port *curp;
1009 void *all;
1010 int i;
1011 unsigned long flags;
1013 if ((all = kmalloc(sizeof(struct js_port) + 4 * devs * sizeof(void*) + infos, GFP_KERNEL)) == NULL)
1014 return NULL;
1016 curp = all;
1018 curp->next = NULL;
1019 curp->prev = port;
1020 curp->read = read;
1021 curp->ndevs = devs;
1023 curp->devs = all += sizeof(struct js_port);
1024 for (i = 0; i < devs; i++) curp->devs[i] = NULL;
1026 curp->axes = all += devs * sizeof(void*);
1027 curp->buttons = (void*) all += devs * sizeof(void*);
1028 curp->corr = all += devs * sizeof(void*);
1030 if (infos) {
1031 curp->info = all += devs * sizeof(void*);
1032 memcpy(curp->info, info, infos);
1033 } else {
1034 curp->info = NULL;
1037 spin_lock_irqsave(&js_lock, flags);
1039 while (*ptrp != NULL) ptrp=&((*ptrp)->next);
1040 *ptrp = curp;
1042 spin_unlock_irqrestore(&js_lock, flags);
1044 return curp;
1047 struct js_port *js_unregister_port(struct js_port *port)
1049 struct js_port **curp = &js_port;
1050 struct js_port *prev;
1051 unsigned long flags;
1053 spin_lock_irqsave(&js_lock, flags);
1055 while (*curp != NULL && (*curp != port)) curp = &((*curp)->next);
1056 *curp = (*curp)->next;
1058 spin_unlock_irqrestore(&js_lock, flags);
1060 prev = port->prev;
1061 kfree(port);
1063 return prev;
1066 int js_register_device(struct js_port *port, int number, int axes, int buttons, char *name,
1067 js_ops_func open, js_ops_func close)
1069 struct js_dev **ptrd = &js_dev;
1070 struct js_dev *curd;
1071 void *all;
1072 int i = 0;
1073 unsigned long flags;
1075 if ((all = kmalloc(sizeof(struct js_dev) + 2 * axes * sizeof(int) +
1076 2 * (((buttons - 1) >> 5) + 1) * sizeof(int) +
1077 axes * sizeof(struct js_corr) + strlen(name) + 1, GFP_KERNEL)) == NULL)
1078 return -1;
1080 curd = all;
1082 curd->next = NULL;
1083 curd->list = NULL;
1084 curd->port = port;
1085 init_waitqueue_head(&curd->wait);
1086 curd->open = open;
1087 curd->close = close;
1089 curd->ahead = 0;
1090 curd->bhead = 0;
1091 curd->tail = JS_BUFF_SIZE - 1;
1092 curd->num_axes = axes;
1093 curd->num_buttons = buttons;
1095 curd->cur.axes = all += sizeof(struct js_dev);
1096 curd->cur.buttons = all += axes * sizeof(int);
1097 curd->new.axes = all += (((buttons - 1) >> 5) + 1) * sizeof(int);
1098 curd->new.buttons = all += axes * sizeof(int);
1099 curd->corr = all += (((buttons -1 ) >> 5) + 1) * sizeof(int);
1101 curd->name = all += axes * sizeof(struct js_corr);
1102 strcpy(curd->name, name);
1104 port->devs[number] = curd;
1105 port->axes[number] = curd->new.axes;
1106 port->buttons[number] = curd->new.buttons;
1107 port->corr[number] = curd->corr;
1109 spin_lock_irqsave(&js_lock, flags);
1111 while (*ptrd != NULL) { ptrd=&(*ptrd)->next; i++; }
1112 *ptrd = curd;
1114 spin_unlock_irqrestore(&js_lock, flags);
1116 return i;
1119 void js_unregister_device(struct js_dev *dev)
1121 struct js_dev **curd = &js_dev;
1122 unsigned long flags;
1124 spin_lock_irqsave(&js_lock, flags);
1126 while (*curd != NULL && (*curd != dev)) curd = &((*curd)->next);
1127 *curd = (*curd)->next;
1129 spin_unlock_irqrestore(&js_lock, flags);
1131 kfree(dev);
1135 * The operations structure.
1138 static struct file_operations js_fops =
1140 read: js_read,
1141 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
1142 poll: js_poll,
1143 #else
1144 select: js_select,
1145 #endif
1146 ioctl: js_ioctl,
1147 open: js_open,
1148 release: js_release,
1152 * js_init() registers the driver and calls the probe function.
1153 * also initializes some crucial variables.
1156 #ifdef MODULE
1157 int init_module(void)
1158 #else
1159 int __init js_init(void)
1160 #endif
1162 int result;
1164 js_setup_time();
1166 if (register_chrdev(JOYSTICK_MAJOR, "js", &js_fops)) {
1167 printk(KERN_ERR "js: unable to get major %d for joystick\n", JOYSTICK_MAJOR);
1168 return -EBUSY;
1171 spin_lock_init(&js_lock);
1173 init_timer(&js_timer);
1174 js_timer.function = js_do_timer;
1175 js_timer.data = 1;
1177 memset(&js_comp_glue, 0, sizeof(struct JS_DATA_SAVE_TYPE));
1178 js_comp_glue.JS_TIMEOUT = JS_DEF_TIMEOUT;
1179 js_comp_glue.JS_TIMELIMIT = JS_DEF_TIMELIMIT;
1181 #ifdef MODULE
1182 result = 0;
1183 #else
1184 result = -ENODEV;
1185 #ifdef CONFIG_JOY_LIGHTNING
1186 if (!js_l4_init()) result = 0;
1187 #endif
1188 #ifdef CONFIG_JOY_SIDEWINDER
1189 if (!js_sw_init()) result = 0;
1190 #endif
1191 #ifdef CONFIG_JOY_ASSASIN
1192 if (!js_as_init()) result = 0;
1193 #endif
1194 #ifdef CONFIG_JOY_LOGITECH
1195 if (!js_lt_init()) result = 0;
1196 #endif
1197 #ifdef CONFIG_JOY_THRUSTMASTER
1198 if (!js_tm_init()) result = 0;
1199 #endif
1200 #ifdef CONFIG_JOY_GRAVIS
1201 if (!js_gr_init()) result = 0;
1202 #endif
1203 #ifdef CONFIG_JOY_ANALOG
1204 if (!js_an_init()) result = 0;
1205 #endif
1206 #ifdef CONFIG_JOY_CONSOLE
1207 if (!js_console_init()) result = 0;
1208 #endif
1209 #ifdef CONFIG_JOY_DB9
1210 if (!js_db9_init()) result = 0;
1211 #endif
1212 #ifdef CONFIG_JOY_AMIGA
1213 if (!js_am_init()) result = 0;
1214 #endif
1215 if (result) printk(KERN_ERR "js: no joysticks found\n");
1216 #endif
1218 return result;
1222 * cleanup_module() handles module removal.
1225 #ifdef MODULE
1226 void cleanup_module(void)
1228 del_timer(&js_timer);
1229 if (unregister_chrdev(JOYSTICK_MAJOR, "js"))
1230 printk(KERN_ERR "js: can't unregister device\n");
1232 #endif