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 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
46 #include <linux/spinlock.h>
47 #include <linux/poll.h>
51 * Configurable parameters.
54 #define JS_REFRESH_TIME HZ/50 /* Time between two reads of joysticks (20ms) */
60 #define ROT(A,B,C) ((((A)<(C))&&(((B)>(A))&&((B)<(C))))||(((A)>(C))&&(((B)>(A))||((B)<(C)))))
61 #define GOF(X) (((X)==JS_BUFF_SIZE-1)?0:(X)+1)
62 #define GOB(X) ((X)?(X)-1:JS_BUFF_SIZE-1)
63 #define DIFF(X,Y) ((X)>(Y)?(X)-(Y):(Y)-(X))
69 static struct JS_DATA_SAVE_TYPE js_comp_glue
;
70 static struct js_port
*js_port
= NULL
;
71 static struct js_dev
*js_dev
= NULL
;
72 static struct timer_list js_timer
;
73 spinlock_t js_lock
= SPIN_LOCK_UNLOCKED
;
74 static int js_use_count
= 0;
80 unsigned int js_time_speed
= 0;
81 js_time_func js_get_time
;
82 js_delta_func js_delta
;
84 unsigned int js_time_speed_a
= 0;
85 js_time_func js_get_time_a
;
86 js_delta_func js_delta_a
;
92 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
93 MODULE_SUPPORTED_DEVICE("js");
96 * js_get_time_*() are different functions to get current time.
97 * js_delta_*() are functions to compute time difference.
102 static unsigned int js_get_time_rdtsc(void)
105 __asm__
__volatile__ ( "rdtsc" : "=A" (x
) );
109 static unsigned int js_get_time_pit(void)
119 __restore_flags(flags
);
124 static int js_delta_pit(unsigned int x
, unsigned int y
)
126 return y
- x
+ ( y
< x
? 1193180L / HZ
: 0 );
129 static unsigned int js_get_time_counter(void)
131 static int time_counter
= 0;
132 return time_counter
++;
138 static unsigned int js_get_time_rpcc(void)
141 __asm__
__volatile__ ( "rpcc %0" : "=r" (x
) );
148 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
149 static unsigned int js_get_time_system(void)
151 static struct timeval js_tv
;
152 get_fast_time(&js_tv
);
153 return js_tv
.tv_sec
* 1000000L + js_tv
.tv_usec
;
161 static int js_delta_normal(unsigned int x
, unsigned int y
)
167 * js_calibrate_time() calibrates a given timer.
170 static int __init
js_calibrate_time(js_time_func get_time
, js_delta_func delta
)
172 unsigned int t1
, t2
, t3
;
181 __restore_flags(flags
);
183 return delta(t2
, t1
) - delta(t3
, t2
);
187 * js_calibrate_time_counter() calibrates the counter timer, which can't
188 * be calibrated using the above function.
193 static int __init
js_calibrate_time_counter(void)
195 unsigned int i
, j
, t1
, t2
, t3
;
197 j
= jiffies
; do { inb(0x201); t1
= js_get_time_counter(); } while (j
== jiffies
);
198 j
= jiffies
; do { inb(0x201); t2
= js_get_time_counter(); } while (j
== jiffies
);
200 j
= (t2
- t1
) * HZ
/ 1000;
202 t1
= js_get_time_pit();
203 for (i
= 0; i
< 1000; i
++) {
205 js_get_time_counter();
207 t2
= js_get_time_pit();
208 t3
= js_get_time_pit();
210 i
= 1193180L / (js_delta_pit(t2
, t1
) - js_delta_pit(t3
, t2
));
213 printk(KERN_WARNING
"js: Counter timer calibration unsure,"
214 " pass1 (0.%d MHz) and pass2 (0.%d MHz) differ.\n", j
, i
);
222 * js_setup_time chooses the best available timers
223 * on the system and calibrates them.
226 static int __init
js_setup_time(void)
238 t
= js_calibrate_time(js_get_time_pit
, js_delta_pit
);
240 if (DIFF(t
, 1193) > 5)
241 printk(KERN_WARNING
"js: Measured PIT speed is %d.%03d MHz, but should be 1.193 MHz.\n"
242 KERN_WARNING
"js: This is probably caused by wrong BogoMIPS value. It is: %ld, should be: %ld.\n",
243 t
/ 1000, t
% 1000, loops_per_sec
/ 500000, loops_per_sec
/ (t
* 500000 / 1193));
245 if (JS_HAS_RDTSC
&& (t
= js_calibrate_time(js_get_time_rdtsc
, js_delta_normal
)) > 0) {
248 js_get_time_a
= js_get_time_rdtsc
;
249 js_delta_a
= js_delta_normal
;
251 js_get_time
= js_get_time_rdtsc
;
252 js_delta
= js_delta_normal
;
258 js_get_time_a
= js_get_time_pit
;
259 js_delta_a
= js_delta_pit
;
262 t
= js_calibrate_time_counter();
265 js_get_time
= js_get_time_counter
;
266 js_delta
= js_delta_normal
;
274 t
= js_calibrate_time(js_get_time_rpcc
, js_delta_normal
);
277 js_get_time_a
= js_get_time_rpcc
;
278 js_delta_a
= js_delta_normal
;
280 js_get_time
= js_get_time_rpcc
;
281 js_delta
= js_delta_normal
;
287 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
288 t
= js_calibrate_time(js_get_time_system
, js_delta_normal
);
291 js_get_time_a
= js_get_time_system
;
292 js_delta_a
= js_delta_normal
;
294 js_get_time
= js_get_time_system
;
295 js_delta
= js_delta_normal
;
303 printk(KERN_INFO
"js: Version %d.%d.%d ",
304 JS_VERSION
>> 16 & 0xff, JS_VERSION
>> 8 & 0xff, JS_VERSION
& 0xff);
306 if (js_time_speed_a
<= 0 || js_time_speed
<= 0) {
313 if (js_time_speed
> 10000) {
314 t
= js_time_speed
/ 1000 + (js_time_speed
% 1000 >= 500);
315 printk("%d MHz ", t
);
317 t
= js_time_speed
/ 10 + (js_time_speed
% 10 >= 5);
318 printk("%d.%02d MHz ", t
/ 100, t
% 100);
321 if (js_get_time_a
!= js_get_time
) {
322 t
= js_time_speed_a
/ 10 + (js_time_speed_a
% 10 >= 5);
323 printk("%s timer and %d.%02d MHz %s timer.\n",
324 name
, t
/ 100, t
% 100, name_a
);
326 printk("%s timer.\n", name
);
334 * js_correct() performs correction of raw joystick data.
337 static int js_correct(int value
, struct js_corr
*corr
)
339 switch (corr
->type
) {
343 value
= value
> corr
->coef
[0] ? (value
< corr
->coef
[1] ? 0 :
344 ((corr
->coef
[3] * (value
- corr
->coef
[1])) >> 14)) :
345 ((corr
->coef
[2] * (value
- corr
->coef
[0])) >> 14);
352 if (value
< -32767) return -32767;
353 if (value
> 32767) return 32767;
359 * js_button() returns value of button number i.
362 static inline int js_button(int *buttons
, int i
)
364 return (buttons
[i
>> 5] >> (i
& 0x1f)) & 1;
369 * js_add_event() adds an event to the buffer. This requires additional
370 * queue post-processing done by js_sync_buff.
373 static void js_add_event(struct js_dev
*jd
, __u32 time
, __u8 type
, __u8 number
, __s16 value
)
375 jd
->buff
[jd
->ahead
].time
= time
;
376 jd
->buff
[jd
->ahead
].type
= type
;
377 jd
->buff
[jd
->ahead
].number
= number
;
378 jd
->buff
[jd
->ahead
].value
= value
;
379 if (++jd
->ahead
== JS_BUFF_SIZE
) jd
->ahead
= 0;
383 * js_flush_data() does the same as js_process_data, except for that it doesn't
384 * generate any events - it just copies the data from new to cur.
387 static void js_flush_data(struct js_dev
*jd
)
391 for (i
= 0; i
< ((jd
->num_buttons
- 1) >> 5) + 1; i
++)
392 jd
->cur
.buttons
[i
] = jd
->new.buttons
[i
];
393 for (i
= 0; i
< jd
->num_axes
; i
++)
394 jd
->cur
.axes
[i
] = jd
->new.axes
[i
];
398 * js_process_data() finds changes in button states and axis positions and adds
399 * them as events to the buffer.
402 static void js_process_data(struct js_dev
*jd
)
406 for (i
= 0; i
< jd
->num_buttons
; i
++)
407 if ((t
= js_button(jd
->new.buttons
, i
)) != js_button(jd
->cur
.buttons
, i
)) {
408 js_add_event(jd
, jiffies
, JS_EVENT_BUTTON
, i
, t
);
409 jd
->cur
.buttons
[i
>> 5] ^= (1 << (i
& 0x1f));
412 for (i
= 0; i
< jd
->num_axes
; i
++) {
413 t
= js_correct(jd
->new.axes
[i
], &jd
->corr
[i
]);
414 if (((jd
->corr
[i
].prec
== -1) && t
) ||
415 ((DIFF(jd
->new.axes
[i
], jd
->cur
.axes
[i
]) > jd
->corr
[i
].prec
) &&
416 (t
!= js_correct(jd
->cur
.axes
[i
], &jd
->corr
[i
])))) {
417 js_add_event(jd
, jiffies
, JS_EVENT_AXIS
, i
, t
);
418 jd
->cur
.axes
[i
] = jd
->new.axes
[i
];
424 * js_sync_buff() checks for all overflows caused by recent additions to the buffer.
425 * These happen only if some process is reading the data too slowly. It
426 * wakes up any process waiting for data.
429 static void js_sync_buff(struct js_dev
*jd
)
431 struct js_list
*curl
= jd
->list
;
433 if (jd
->bhead
!= jd
->ahead
) {
434 if(ROT(jd
->bhead
, jd
->tail
, jd
->ahead
) || (jd
->tail
== jd
->bhead
)) {
436 if (ROT(jd
->bhead
, curl
->tail
, jd
->ahead
) || (curl
->tail
== jd
->bhead
)) {
437 curl
->tail
= jd
->ahead
;
442 jd
->tail
= jd
->ahead
;
444 jd
->bhead
= jd
->ahead
;
445 wake_up_interruptible(&jd
->wait
);
450 * js_do_timer() acts as an interrupt replacement. It reads the data
451 * from all ports and then generates events for all devices.
454 static void js_do_timer(unsigned long data
)
456 struct js_port
*curp
= js_port
;
457 struct js_dev
*curd
= js_dev
;
460 while (curp
!= NULL
) {
461 curp
->read(curp
->info
, curp
->axes
, curp
->buttons
);
465 spin_lock_irqsave(&js_lock
, flags
);
467 while (curd
!= NULL
) {
469 js_process_data(curd
);
477 spin_unlock_irqrestore(&js_lock
, flags
);
479 js_timer
.expires
= jiffies
+ JS_REFRESH_TIME
;
480 add_timer(&js_timer
);
484 * js_read() copies one or more entries from jsd[].buff to user
488 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
489 static ssize_t
js_read(struct file
*file
, char *buf
, size_t count
, loff_t
*ppos
)
491 static int js_read(struct inode
*inode
, struct file
*file
, char *buf
, int count
)
494 DECLARE_WAITQUEUE(wait
, current
);
495 struct js_event
*buff
= (void *) buf
;
496 struct js_list
*curl
;
498 unsigned long blocks
= count
/ sizeof(struct js_event
);
500 int new_tail
, orig_tail
;
504 curl
= file
->private_data
;
506 orig_tail
= curl
->tail
;
519 spin_lock_irqsave(&js_lock
, flags
);
522 * Handle (non)blocking i/o.
524 if (count
!= sizeof(struct JS_DATA_TYPE
)) {
526 if (GOF(curl
->tail
) == jd
->bhead
&& curl
->startup
== jd
->num_axes
+ jd
->num_buttons
) {
528 __set_current_state(TASK_INTERRUPTIBLE
);
529 add_wait_queue(&jd
->wait
, &wait
);
531 while (GOF(curl
->tail
) == jd
->bhead
) {
533 if (file
->f_flags
& O_NONBLOCK
) {
537 if (signal_pending(current
)) {
538 retval
= -ERESTARTSYS
;
542 spin_unlock_irqrestore(&js_lock
, flags
);
544 spin_lock_irqsave(&js_lock
, flags
);
548 current
->state
= TASK_RUNNING
;
549 remove_wait_queue(&jd
->wait
, &wait
);
553 spin_unlock_irqrestore(&js_lock
, flags
);
561 while (curl
->startup
< jd
->num_axes
+ jd
->num_buttons
&& written
< blocks
&& !retval
) {
563 struct js_event tmpevent
;
565 if (curl
->startup
< jd
->num_buttons
) {
566 tmpevent
.type
= JS_EVENT_BUTTON
| JS_EVENT_INIT
;
567 tmpevent
.value
= js_button(jd
->cur
.buttons
, curl
->startup
);
568 tmpevent
.number
= curl
->startup
;
570 tmpevent
.type
= JS_EVENT_AXIS
| JS_EVENT_INIT
;
571 tmpevent
.value
= js_correct(jd
->cur
.axes
[curl
->startup
- jd
->num_buttons
],
572 &jd
->corr
[curl
->startup
- jd
->num_buttons
]);
573 tmpevent
.number
= curl
->startup
- jd
->num_buttons
;
576 tmpevent
.time
= jiffies
* (1000/HZ
);
578 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
579 if (copy_to_user(&buff
[written
], &tmpevent
, sizeof(struct js_event
)))
582 if (!(retval
= verify_area(VERIFY_WRITE
, &buff
[written
], sizeof(struct js_event
))))
583 memcpy_tofs(&buff
[written
], &tmpevent
, sizeof(struct js_event
));
594 while ((jd
->bhead
!= (new_tail
= GOF(curl
->tail
))) && (written
< blocks
) && !retval
) {
596 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
597 if (copy_to_user(&buff
[written
], &jd
->buff
[new_tail
], sizeof(struct js_event
)))
599 if (put_user((__u32
)(jd
->buff
[new_tail
].time
* (1000/HZ
)), &buff
[written
].time
))
602 if (!(retval
= verify_area(VERIFY_WRITE
, &buff
[written
], sizeof(struct js_event
)))) {
603 memcpy_tofs(&buff
[written
], &jd
->buff
[new_tail
], sizeof(struct js_event
));
604 put_user((__u32
)(jd
->buff
[new_tail
].time
* (1000/HZ
)), &buff
[written
].time
);
607 curl
->tail
= new_tail
;
615 * Handle version 0.x compatibility.
619 struct JS_DATA_TYPE data
;
621 data
.buttons
= jd
->new.buttons
[0];
622 data
.x
= jd
->num_axes
< 1 ? 0 :
623 ((js_correct(jd
->new.axes
[0], &jd
->corr
[0]) / 256) + 128) >> js_comp_glue
.JS_CORR
.x
;
624 data
.y
= jd
->num_axes
< 2 ? 0 :
625 ((js_correct(jd
->new.axes
[1], &jd
->corr
[1]) / 256) + 128) >> js_comp_glue
.JS_CORR
.y
;
627 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
628 retval
= copy_to_user(buf
, &data
, sizeof(struct JS_DATA_TYPE
)) ? -EFAULT
: 0;
630 if (!(retval
= verify_area(VERIFY_WRITE
, buf
, sizeof(struct JS_DATA_TYPE
)))) {
631 memcpy_tofs(buf
, &data
, sizeof(struct JS_DATA_TYPE
));
636 curl
->tail
= GOB(jd
->bhead
);
637 if (!retval
) retval
= sizeof(struct JS_DATA_TYPE
);
641 * Check main tail and move it.
644 if (orig_tail
== jd
->tail
) {
645 new_tail
= curl
->tail
;
647 while (curl
!= NULL
&& curl
->tail
!= jd
->tail
) {
648 if (ROT(jd
->bhead
, new_tail
, curl
->tail
) ||
649 (jd
->bhead
== curl
->tail
)) new_tail
= curl
->tail
;
652 if (curl
== NULL
) jd
->tail
= new_tail
;
655 spin_unlock_irqrestore(&js_lock
, flags
);
657 return retval
? retval
: written
* sizeof(struct js_event
);
661 * js_poll() does select() support.
664 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
666 static unsigned int js_poll(struct file
*file
, poll_table
*wait
)
668 struct js_list
*curl
= file
->private_data
;
671 poll_wait(file
, &curl
->dev
->wait
, wait
);
672 spin_lock_irqsave(&js_lock
, flags
);
673 if (GOF(curl
->tail
) != curl
->dev
->bhead
||
674 curl
->startup
< curl
->dev
->num_axes
+ curl
->dev
->num_buttons
) retval
= POLLIN
| POLLRDNORM
;
675 spin_unlock_irqrestore(&js_lock
, flags
);
681 static int js_select(struct inode
*inode
, struct file
*file
, int sel_type
, select_table
*wait
)
683 struct js_list
*curl
= file
->private_data
;
684 if (sel_type
== SEL_IN
) {
685 if (GOF(curl
->tail
) != curl
->dev
->bhead
) return 1;
686 select_wait(&curl
->dev
->wait
, wait
);
694 * js_ioctl handles misc ioctl calls.
697 static int js_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
, unsigned long arg
)
699 struct js_list
*curl
;
703 curl
= file
->private_data
;
706 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
715 return copy_from_user(&js_comp_glue
.JS_CORR
, (struct JS_DATA_TYPE
*) arg
,
716 sizeof(struct JS_DATA_TYPE
)) ? -EFAULT
: 0;
718 return copy_to_user((struct JS_DATA_TYPE
*) arg
, &js_comp_glue
.JS_CORR
,
719 sizeof(struct JS_DATA_TYPE
)) ? -EFAULT
: 0;
721 return get_user(js_comp_glue
.JS_TIMEOUT
, (int *) arg
);
723 return put_user(js_comp_glue
.JS_TIMEOUT
, (int *) arg
);
724 case JS_SET_TIMELIMIT
:
725 return get_user(js_comp_glue
.JS_TIMELIMIT
, (long *) arg
);
726 case JS_GET_TIMELIMIT
:
727 return put_user(js_comp_glue
.JS_TIMELIMIT
, (long *) arg
);
729 return copy_from_user(&js_comp_glue
, (struct JS_DATA_SAVE_TYPE
*) arg
,
730 sizeof(struct JS_DATA_SAVE_TYPE
)) ? -EFAULT
: 0;
732 return copy_to_user((struct JS_DATA_SAVE_TYPE
*) arg
, &js_comp_glue
,
733 sizeof(struct JS_DATA_SAVE_TYPE
)) ? -EFAULT
: 0;
740 return put_user(JS_VERSION
, (__u32
*) arg
);
742 return put_user(jd
->num_axes
, (__u8
*) arg
);
744 return put_user(jd
->num_buttons
, (__u8
*) arg
);
746 return copy_from_user(jd
->corr
, (struct js_corr
*) arg
,
747 sizeof(struct js_corr
) * jd
->num_axes
) ? -EFAULT
: 0;
749 return copy_to_user((struct js_corr
*) arg
, jd
->corr
,
750 sizeof(struct js_corr
) * jd
->num_axes
) ? -EFAULT
: 0;
752 if ((cmd
& ~(_IOC_SIZEMASK
<< _IOC_SIZESHIFT
)) == JSIOCGNAME(0)) {
753 len
= strlen(jd
->name
) + 1;
754 if (len
> _IOC_SIZE(cmd
)) len
= _IOC_SIZE(cmd
);
755 if (copy_to_user((char *) arg
, jd
->name
, len
)) return -EFAULT
;
769 if (verify_area(VERIFY_READ
, (struct JS_DATA_TYPE
*) arg
,
770 sizeof(struct JS_DATA_TYPE
))) return -EFAULT
;
771 memcpy_fromfs(&js_comp_glue
.JS_CORR
, (struct JS_DATA_SAVE_TYPE
*) arg
,
772 sizeof(struct JS_DATA_TYPE
));
775 if (verify_area(VERIFY_WRITE
, (struct JS_DATA_TYPE
*) arg
,
776 sizeof(struct JS_DATA_TYPE
))) return -EFAULT
;
777 memcpy_tofs((struct JS_DATA_SAVE_TYPE
*) arg
, &js_comp_glue
.JS_CORR
,
778 sizeof(struct JS_DATA_TYPE
));
781 if (verify_area(VERIFY_READ
, (int *) arg
, sizeof(int))) return -EFAULT
;
782 js_comp_glue
.JS_TIMEOUT
= get_user((int *) arg
);
785 if (verify_area(VERIFY_WRITE
, (int *) arg
, sizeof(int))) return -EFAULT
;
786 put_user(js_comp_glue
.JS_TIMEOUT
, (int *) arg
);
788 case JS_SET_TIMELIMIT
:
789 if (verify_area(VERIFY_READ
, (long *) arg
, sizeof(long))) return -EFAULT
;
790 js_comp_glue
.JS_TIMELIMIT
= get_user((long *) arg
);
792 case JS_GET_TIMELIMIT
:
793 if (verify_area(VERIFY_WRITE
, (long *) arg
, sizeof(long))) return -EFAULT
;
794 put_user(js_comp_glue
.JS_TIMELIMIT
, (long *) arg
);
797 if (verify_area(VERIFY_READ
, (struct JS_DATA_SAVE_TYPE
*) arg
,
798 sizeof(struct JS_DATA_SAVE_TYPE
))) return -EFAULT
;
799 memcpy_fromfs(&js_comp_glue
, (struct JS_DATA_SAVE_TYPE
*) arg
,
800 sizeof(struct JS_DATA_SAVE_TYPE
));
803 if (verify_area(VERIFY_WRITE
, (struct JS_DATA_SAVE_TYPE
*) arg
,
804 sizeof(struct JS_DATA_SAVE_TYPE
))) return -EFAULT
;
805 memcpy_tofs((struct JS_DATA_SAVE_TYPE
*) arg
, &js_comp_glue
,
806 sizeof(struct JS_DATA_SAVE_TYPE
));
814 if (verify_area(VERIFY_WRITE
, (__u32
*) arg
, sizeof(__u32
))) return -EFAULT
;
815 put_user(JS_VERSION
, (__u32
*) arg
);
818 if (verify_area(VERIFY_WRITE
, (__u8
*) arg
, sizeof(__u8
))) return -EFAULT
;
819 put_user(jd
->num_axes
, (__u8
*) arg
);
822 if (verify_area(VERIFY_WRITE
, (__u8
*) arg
, sizeof(__u8
))) return -EFAULT
;
823 put_user(jd
->num_buttons
, (__u8
*) arg
);
826 if (verify_area(VERIFY_READ
, (struct js_corr
*) arg
,
827 sizeof(struct js_corr
) * jd
->num_axes
)) return -EFAULT
;
828 memcpy_fromfs(jd
->corr
, (struct js_corr
*) arg
,
829 sizeof(struct js_corr
) * jd
->num_axes
);
832 if (verify_area(VERIFY_WRITE
, (struct js_corr
*) arg
,
833 sizeof(struct js_corr
) * jd
->num_axes
)) return -EFAULT
;
834 memcpy_tofs((struct js_corr
*) arg
,
835 jd
->corr
, sizeof(struct js_corr
) * jd
->num_axes
);
838 if ((cmd
& ~(_IOC_SIZEMASK
<< _IOC_SIZESHIFT
)) == JSIOCGNAME(0)) {
839 len
= strlen(jd
->name
) + 1;
840 if (verify_area(VERIFY_WRITE
, (char *) arg
, len
)) return -EFAULT
;
841 if (len
> _IOC_SIZE(cmd
)) len
= _IOC_SIZE(cmd
);
842 memcpy_tofs((char *) arg
, jd
->name
, len
);
853 * js_open() performs necessary initialization and adds
854 * an entry to the linked list.
857 static int js_open(struct inode
*inode
, struct file
*file
)
859 struct js_list
*curl
, *new;
860 struct js_dev
*jd
= js_dev
;
861 int i
= MINOR(inode
->i_rdev
);
865 if (MAJOR(inode
->i_rdev
) != JOYSTICK_MAJOR
)
868 spin_lock_irqsave(&js_lock
, flags
);
870 while (i
> 0 && jd
!= NULL
) {
875 spin_unlock_irqrestore(&js_lock
, flags
);
877 if (jd
== NULL
) return -ENODEV
;
879 if ((result
= jd
->open(jd
))) return result
;
882 if (!js_use_count
++) js_do_timer(0);
884 if ((new = kmalloc(sizeof(struct js_list
), GFP_KERNEL
)) != NULL
) {
886 spin_lock_irqsave(&js_lock
, flags
);
891 jd
->list
->next
= curl
;
893 jd
->list
->startup
= 0;
894 jd
->list
->tail
= GOB(jd
->bhead
);
895 file
->private_data
= jd
->list
;
897 spin_unlock_irqrestore(&js_lock
, flags
);
907 * js_release() removes an entry from list and deallocates memory
911 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
912 static int js_release(struct inode
*inode
, struct file
*file
)
914 static void js_release(struct inode
*inode
, struct file
*file
)
917 struct js_list
*curl
= file
->private_data
;
918 struct js_dev
*jd
= curl
->dev
;
919 struct js_list
**curp
= &jd
->list
;
923 spin_lock_irqsave(&js_lock
, flags
);
925 while (*curp
&& (*curp
!= curl
)) curp
= &((*curp
)->next
);
926 *curp
= (*curp
)->next
;
928 if (jd
->list
!= NULL
)
929 if (curl
->tail
== jd
->tail
) {
931 new_tail
= curl
->tail
;
932 while (curl
!= NULL
&& curl
->tail
!= jd
->tail
) {
933 if (ROT(jd
->bhead
, new_tail
, curl
->tail
) ||
934 (jd
->bhead
== curl
->tail
)) new_tail
= curl
->tail
;
937 if (!curl
) jd
->tail
= new_tail
;
940 spin_unlock_irqrestore(&js_lock
, flags
);
942 kfree(file
->private_data
);
944 if (!--js_use_count
) del_timer(&js_timer
);
949 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
955 * js_dump_mem() dumps all data structures in memory.
956 * It's used for debugging only.
960 static void js_dump_mem(void)
963 struct js_port
*curp
= js_port
;
964 struct js_dev
*curd
= js_dev
;
967 printk(",--- Dumping Devices:\n");
968 printk("| js_dev = %x\n", (int) js_dev
);
970 while (curd
!= NULL
) {
971 printk("| %s-device %x, next %x axes %d, buttons %d, port %x - %#x\n",
972 curd
->next
? "|":"`",
973 (int) curd
, (int) curd
->next
, curd
->num_axes
, curd
->num_buttons
, (int) curd
->port
, curd
->port
->io
);
977 printk(">--- Dumping ports:\n");
978 printk("| js_port = %x\n", (int) js_port
);
980 while (curp
!= NULL
) {
981 printk("| %s-port %x, next %x, io %#x, devices %d\n",
982 curp
->next
? "|":"`",
983 (int) curp
, (int) curp
->next
, curp
->io
, curp
->ndevs
);
984 for (i
= 0; i
< curp
->ndevs
; i
++) {
985 curd
= curp
->devs
[i
];
987 printk("| %s %s-device %x, next %x axes %d, buttons %d, port %x\n",
988 curp
->next
? "|":" ", (i
< curp
->ndevs
-1) ? "|":"`",
989 (int) curd
, (int) curd
->next
, curd
->num_axes
, curd
->num_buttons
, (int) curd
->port
);
991 printk("| %s %s-device %x, not there\n",
992 curp
->next
? "|":" ", (i
< curp
->ndevs
-1) ? "|":"`", (int) curd
);
998 printk("`--- Done\n");
1003 struct js_port
*js_register_port(struct js_port
*port
,
1004 void *info
, int devs
, int infos
, js_read_func read
)
1006 struct js_port
**ptrp
= &js_port
;
1007 struct js_port
*curp
;
1010 unsigned long flags
;
1012 if ((all
= kmalloc(sizeof(struct js_port
) + 4 * devs
* sizeof(void*) + infos
, GFP_KERNEL
)) == NULL
)
1022 curp
->devs
= all
+= sizeof(struct js_port
);
1023 for (i
= 0; i
< devs
; i
++) curp
->devs
[i
] = NULL
;
1025 curp
->axes
= all
+= devs
* sizeof(void*);
1026 curp
->buttons
= (void*) all
+= devs
* sizeof(void*);
1027 curp
->corr
= all
+= devs
* sizeof(void*);
1030 curp
->info
= all
+= devs
* sizeof(void*);
1031 memcpy(curp
->info
, info
, infos
);
1036 spin_lock_irqsave(&js_lock
, flags
);
1038 while (*ptrp
!= NULL
) ptrp
=&((*ptrp
)->next
);
1041 spin_unlock_irqrestore(&js_lock
, flags
);
1046 struct js_port
*js_unregister_port(struct js_port
*port
)
1048 struct js_port
**curp
= &js_port
;
1049 struct js_port
*prev
;
1050 unsigned long flags
;
1052 spin_lock_irqsave(&js_lock
, flags
);
1054 while (*curp
!= NULL
&& (*curp
!= port
)) curp
= &((*curp
)->next
);
1055 *curp
= (*curp
)->next
;
1057 spin_unlock_irqrestore(&js_lock
, flags
);
1065 int js_register_device(struct js_port
*port
, int number
, int axes
, int buttons
, char *name
,
1066 js_ops_func open
, js_ops_func close
)
1068 struct js_dev
**ptrd
= &js_dev
;
1069 struct js_dev
*curd
;
1072 unsigned long flags
;
1074 if ((all
= kmalloc(sizeof(struct js_dev
) + 2 * axes
* sizeof(int) +
1075 2 * (((buttons
- 1) >> 5) + 1) * sizeof(int) +
1076 axes
* sizeof(struct js_corr
) + strlen(name
) + 1, GFP_KERNEL
)) == NULL
)
1084 init_waitqueue_head(&curd
->wait
);
1086 curd
->close
= close
;
1090 curd
->tail
= JS_BUFF_SIZE
- 1;
1091 curd
->num_axes
= axes
;
1092 curd
->num_buttons
= buttons
;
1094 curd
->cur
.axes
= all
+= sizeof(struct js_dev
);
1095 curd
->cur
.buttons
= all
+= axes
* sizeof(int);
1096 curd
->new.axes
= all
+= (((buttons
- 1) >> 5) + 1) * sizeof(int);
1097 curd
->new.buttons
= all
+= axes
* sizeof(int);
1098 curd
->corr
= all
+= (((buttons
-1 ) >> 5) + 1) * sizeof(int);
1100 curd
->name
= all
+= axes
* sizeof(struct js_corr
);
1101 strcpy(curd
->name
, name
);
1103 port
->devs
[number
] = curd
;
1104 port
->axes
[number
] = curd
->new.axes
;
1105 port
->buttons
[number
] = curd
->new.buttons
;
1106 port
->corr
[number
] = curd
->corr
;
1108 spin_lock_irqsave(&js_lock
, flags
);
1110 while (*ptrd
!= NULL
) { ptrd
=&(*ptrd
)->next
; i
++; }
1113 spin_unlock_irqrestore(&js_lock
, flags
);
1118 void js_unregister_device(struct js_dev
*dev
)
1120 struct js_dev
**curd
= &js_dev
;
1121 unsigned long flags
;
1123 spin_lock_irqsave(&js_lock
, flags
);
1125 while (*curd
!= NULL
&& (*curd
!= dev
)) curd
= &((*curd
)->next
);
1126 *curd
= (*curd
)->next
;
1128 spin_unlock_irqrestore(&js_lock
, flags
);
1134 * The operations structure.
1137 static struct file_operations js_fops
=
1140 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
1147 release
: js_release
,
1151 * js_init() registers the driver and calls the probe function.
1152 * also initializes some crucial variables.
1156 int init_module(void)
1158 int __init
js_init(void)
1165 if (register_chrdev(JOYSTICK_MAJOR
, "js", &js_fops
)) {
1166 printk(KERN_ERR
"js: unable to get major %d for joystick\n", JOYSTICK_MAJOR
);
1170 spin_lock_init(&js_lock
);
1172 init_timer(&js_timer
);
1173 js_timer
.function
= js_do_timer
;
1176 memset(&js_comp_glue
, 0, sizeof(struct JS_DATA_SAVE_TYPE
));
1177 js_comp_glue
.JS_TIMEOUT
= JS_DEF_TIMEOUT
;
1178 js_comp_glue
.JS_TIMELIMIT
= JS_DEF_TIMELIMIT
;
1184 #ifdef CONFIG_JOY_LIGHTNING
1185 if (!js_l4_init()) result
= 0;
1187 #ifdef CONFIG_JOY_SIDEWINDER
1188 if (!js_sw_init()) result
= 0;
1190 #ifdef CONFIG_JOY_ASSASIN
1191 if (!js_as_init()) result
= 0;
1193 #ifdef CONFIG_JOY_LOGITECH
1194 if (!js_lt_init()) result
= 0;
1196 #ifdef CONFIG_JOY_THRUSTMASTER
1197 if (!js_tm_init()) result
= 0;
1199 #ifdef CONFIG_JOY_GRAVIS
1200 if (!js_gr_init()) result
= 0;
1202 #ifdef CONFIG_JOY_ANALOG
1203 if (!js_an_init()) result
= 0;
1205 #ifdef CONFIG_JOY_CONSOLE
1206 if (!js_console_init()) result
= 0;
1208 #ifdef CONFIG_JOY_DB9
1209 if (!js_db9_init()) result
= 0;
1211 #ifdef CONFIG_JOY_AMIGA
1212 if (!js_am_init()) result
= 0;
1214 if (result
) printk(KERN_ERR
"js: no joysticks found\n");
1221 * cleanup_module() handles module removal.
1225 void cleanup_module(void)
1227 del_timer(&js_timer
);
1228 if (unregister_chrdev(JOYSTICK_MAJOR
, "js"))
1229 printk(KERN_ERR
"js: can't unregister device\n");