2 * joystick.c Version 1.2
4 * Copyright (c) 1996-1998 Vojtech Pavlik
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
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>
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>
52 * Configurable parameters.
55 #define JS_REFRESH_TIME HZ/50 /* Time between two reads of joysticks (20ms) */
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))
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;
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
;
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.
103 static unsigned int js_get_time_rdtsc(void)
106 __asm__
__volatile__ ( "rdtsc" : "=A" (x
) );
110 static unsigned int js_get_time_pit(void)
120 __restore_flags(flags
);
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
++;
139 static unsigned int js_get_time_rpcc(void)
142 __asm__
__volatile__ ( "rpcc %0" : "=r" (x
) );
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
;
162 static int js_delta_normal(unsigned int x
, unsigned int 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
;
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.
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
++) {
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
));
214 printk(KERN_WARNING
"js: Counter timer calibration unsure,"
215 " pass1 (0.%d MHz) and pass2 (0.%d MHz) differ.\n", j
, i
);
223 * js_setup_time chooses the best available timers
224 * on the system and calibrates them.
227 static int __init
js_setup_time(void)
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) {
249 js_get_time_a
= js_get_time_rdtsc
;
250 js_delta_a
= js_delta_normal
;
252 js_get_time
= js_get_time_rdtsc
;
253 js_delta
= js_delta_normal
;
259 js_get_time_a
= js_get_time_pit
;
260 js_delta_a
= js_delta_pit
;
263 t
= js_calibrate_time_counter();
266 js_get_time
= js_get_time_counter
;
267 js_delta
= js_delta_normal
;
275 t
= js_calibrate_time(js_get_time_rpcc
, js_delta_normal
);
278 js_get_time_a
= js_get_time_rpcc
;
279 js_delta_a
= js_delta_normal
;
281 js_get_time
= js_get_time_rpcc
;
282 js_delta
= js_delta_normal
;
288 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
289 t
= js_calibrate_time(js_get_time_system
, js_delta_normal
);
292 js_get_time_a
= js_get_time_system
;
293 js_delta_a
= js_delta_normal
;
295 js_get_time
= js_get_time_system
;
296 js_delta
= js_delta_normal
;
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) {
314 if (js_time_speed
> 10000) {
315 t
= js_time_speed
/ 1000 + (js_time_speed
% 1000 >= 500);
316 printk("%d MHz ", t
);
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
);
327 printk("%s timer.\n", name
);
335 * js_correct() performs correction of raw joystick data.
338 static int js_correct(int value
, struct js_corr
*corr
)
340 switch (corr
->type
) {
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);
353 if (value
< -32767) return -32767;
354 if (value
> 32767) return 32767;
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
)
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
)
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
)) {
437 if (ROT(jd
->bhead
, curl
->tail
, jd
->ahead
) || (curl
->tail
== jd
->bhead
)) {
438 curl
->tail
= jd
->ahead
;
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
;
461 while (curp
!= NULL
) {
462 curp
->read(curp
->info
, curp
->axes
, curp
->buttons
);
466 spin_lock_irqsave(&js_lock
, flags
);
468 while (curd
!= NULL
) {
470 js_process_data(curd
);
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
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
)
492 static int js_read(struct inode
*inode
, struct file
*file
, char *buf
, int count
)
495 DECLARE_WAITQUEUE(wait
, current
);
496 struct js_event
*buff
= (void *) buf
;
497 struct js_list
*curl
;
499 unsigned long blocks
= count
/ sizeof(struct js_event
);
501 int new_tail
, orig_tail
;
505 curl
= file
->private_data
;
507 orig_tail
= curl
->tail
;
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
) {
538 if (signal_pending(current
)) {
539 retval
= -ERESTARTSYS
;
543 spin_unlock_irqrestore(&js_lock
, flags
);
545 spin_lock_irqsave(&js_lock
, flags
);
549 current
->state
= TASK_RUNNING
;
550 remove_wait_queue(&jd
->wait
, &wait
);
554 spin_unlock_irqrestore(&js_lock
, flags
);
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
;
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
)))
583 if (!(retval
= verify_area(VERIFY_WRITE
, &buff
[written
], sizeof(struct js_event
))))
584 memcpy_tofs(&buff
[written
], &tmpevent
, sizeof(struct js_event
));
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
)))
600 if (put_user((__u32
)(jd
->buff
[new_tail
].time
* (1000/HZ
)), &buff
[written
].time
))
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
);
608 curl
->tail
= new_tail
;
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;
631 if (!(retval
= verify_area(VERIFY_WRITE
, buf
, sizeof(struct JS_DATA_TYPE
)))) {
632 memcpy_tofs(buf
, &data
, sizeof(struct JS_DATA_TYPE
));
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
;
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
;
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
;
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
);
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
);
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
;
704 curl
= file
->private_data
;
707 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
716 return copy_from_user(&js_comp_glue
.JS_CORR
, (struct JS_DATA_TYPE
*) arg
,
717 sizeof(struct JS_DATA_TYPE
)) ? -EFAULT
: 0;
719 return copy_to_user((struct JS_DATA_TYPE
*) arg
, &js_comp_glue
.JS_CORR
,
720 sizeof(struct JS_DATA_TYPE
)) ? -EFAULT
: 0;
722 return get_user(js_comp_glue
.JS_TIMEOUT
, (int *) arg
);
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
);
730 return copy_from_user(&js_comp_glue
, (struct JS_DATA_SAVE_TYPE
*) arg
,
731 sizeof(struct JS_DATA_SAVE_TYPE
)) ? -EFAULT
: 0;
733 return copy_to_user((struct JS_DATA_SAVE_TYPE
*) arg
, &js_comp_glue
,
734 sizeof(struct JS_DATA_SAVE_TYPE
)) ? -EFAULT
: 0;
741 return put_user(JS_VERSION
, (__u32
*) arg
);
743 return put_user(jd
->num_axes
, (__u8
*) arg
);
745 return put_user(jd
->num_buttons
, (__u8
*) arg
);
747 return copy_from_user(jd
->corr
, (struct js_corr
*) arg
,
748 sizeof(struct js_corr
) * jd
->num_axes
) ? -EFAULT
: 0;
750 return copy_to_user((struct js_corr
*) arg
, jd
->corr
,
751 sizeof(struct js_corr
) * jd
->num_axes
) ? -EFAULT
: 0;
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
;
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
));
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
));
782 if (verify_area(VERIFY_READ
, (int *) arg
, sizeof(int))) return -EFAULT
;
783 js_comp_glue
.JS_TIMEOUT
= get_user((int *) arg
);
786 if (verify_area(VERIFY_WRITE
, (int *) arg
, sizeof(int))) return -EFAULT
;
787 put_user(js_comp_glue
.JS_TIMEOUT
, (int *) arg
);
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
);
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
);
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
));
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
));
815 if (verify_area(VERIFY_WRITE
, (__u32
*) arg
, sizeof(__u32
))) return -EFAULT
;
816 put_user(JS_VERSION
, (__u32
*) arg
);
819 if (verify_area(VERIFY_WRITE
, (__u8
*) arg
, sizeof(__u8
))) return -EFAULT
;
820 put_user(jd
->num_axes
, (__u8
*) arg
);
823 if (verify_area(VERIFY_WRITE
, (__u8
*) arg
, sizeof(__u8
))) return -EFAULT
;
824 put_user(jd
->num_buttons
, (__u8
*) arg
);
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
);
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
);
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
);
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
);
866 if (MAJOR(inode
->i_rdev
) != JOYSTICK_MAJOR
)
869 spin_lock_irqsave(&js_lock
, flags
);
871 while (i
> 0 && jd
!= NULL
) {
876 spin_unlock_irqrestore(&js_lock
, flags
);
878 if (jd
== NULL
) return -ENODEV
;
880 if ((result
= jd
->open(jd
))) return result
;
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
);
892 jd
->list
->next
= curl
;
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
);
908 * js_release() removes an entry from list and deallocates memory
912 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
913 static int js_release(struct inode
*inode
, struct file
*file
)
915 static void js_release(struct inode
*inode
, struct file
*file
)
918 struct js_list
*curl
= file
->private_data
;
919 struct js_dev
*jd
= curl
->dev
;
920 struct js_list
**curp
= &jd
->list
;
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
) {
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
;
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
);
950 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
956 * js_dump_mem() dumps all data structures in memory.
957 * It's used for debugging only.
961 static void js_dump_mem(void)
964 struct js_port
*curp
= js_port
;
965 struct js_dev
*curd
= js_dev
;
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
);
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
];
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
);
992 printk("| %s %s-device %x, not there\n",
993 curp
->next
? "|":" ", (i
< curp
->ndevs
-1) ? "|":"`", (int) curd
);
999 printk("`--- Done\n");
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
;
1011 unsigned long flags
;
1013 if ((all
= kmalloc(sizeof(struct js_port
) + 4 * devs
* sizeof(void*) + infos
, GFP_KERNEL
)) == NULL
)
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*);
1031 curp
->info
= all
+= devs
* sizeof(void*);
1032 memcpy(curp
->info
, info
, infos
);
1037 spin_lock_irqsave(&js_lock
, flags
);
1039 while (*ptrp
!= NULL
) ptrp
=&((*ptrp
)->next
);
1042 spin_unlock_irqrestore(&js_lock
, flags
);
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
);
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
;
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
)
1085 init_waitqueue_head(&curd
->wait
);
1087 curd
->close
= close
;
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
++; }
1114 spin_unlock_irqrestore(&js_lock
, flags
);
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
);
1135 * The operations structure.
1138 static struct file_operations js_fops
=
1141 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
1148 release
: js_release
,
1152 * js_init() registers the driver and calls the probe function.
1153 * also initializes some crucial variables.
1157 int init_module(void)
1159 int __init
js_init(void)
1166 if (register_chrdev(JOYSTICK_MAJOR
, "js", &js_fops
)) {
1167 printk(KERN_ERR
"js: unable to get major %d for joystick\n", JOYSTICK_MAJOR
);
1171 spin_lock_init(&js_lock
);
1173 init_timer(&js_timer
);
1174 js_timer
.function
= js_do_timer
;
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
;
1185 #ifdef CONFIG_JOY_LIGHTNING
1186 if (!js_l4_init()) result
= 0;
1188 #ifdef CONFIG_JOY_SIDEWINDER
1189 if (!js_sw_init()) result
= 0;
1191 #ifdef CONFIG_JOY_ASSASIN
1192 if (!js_as_init()) result
= 0;
1194 #ifdef CONFIG_JOY_LOGITECH
1195 if (!js_lt_init()) result
= 0;
1197 #ifdef CONFIG_JOY_THRUSTMASTER
1198 if (!js_tm_init()) result
= 0;
1200 #ifdef CONFIG_JOY_GRAVIS
1201 if (!js_gr_init()) result
= 0;
1203 #ifdef CONFIG_JOY_ANALOG
1204 if (!js_an_init()) result
= 0;
1206 #ifdef CONFIG_JOY_CONSOLE
1207 if (!js_console_init()) result
= 0;
1209 #ifdef CONFIG_JOY_DB9
1210 if (!js_db9_init()) result
= 0;
1212 #ifdef CONFIG_JOY_AMIGA
1213 if (!js_am_init()) result
= 0;
1215 if (result
) printk(KERN_ERR
"js: no joysticks found\n");
1222 * cleanup_module() handles module removal.
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");