diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
commit | 78c388aed2b7184182c08428db1de6c872d815f5 (patch) | |
tree | 4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /drivers/char/joystick.c | |
parent | eb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff) |
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'drivers/char/joystick.c')
-rw-r--r-- | drivers/char/joystick.c | 861 |
1 files changed, 0 insertions, 861 deletions
diff --git a/drivers/char/joystick.c b/drivers/char/joystick.c deleted file mode 100644 index 4f940f4d5..000000000 --- a/drivers/char/joystick.c +++ /dev/null @@ -1,861 +0,0 @@ -/* - * linux/drivers/char/joystick.c Version 1.0.9 - * Copyright (C) 1996-1998 Vojtech Pavlik - */ - -/* - * This is joystick driver for Linux. It supports up to two analog joysticks - * on a PC compatible machine. See Documentation/joystick.txt for changelog - * and credits. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/errno.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/malloc.h> -#include <linux/poll.h> -#include <linux/major.h> -#include <linux/joystick.h> -#include <asm/io.h> - -#define PIT_HZ 1193180L /* PIT clock is 1.19318 MHz */ - -#define JS_MAXTIME PIT_HZ/250 /* timeout for read (4 ms) */ - -#define JS_TIMER_PERIOD HZ/50 /* button valid time (20 ms) */ -#define JS_BH_MIN_PERIOD HZ/25 /* axis min valid time (40 ms) */ -#define JS_BH_MAX_PERIOD HZ/25*2 /* axis max valid time (80 ms) */ - -#define JS_FIFO_SIZE 16 /* number of FIFO entries */ -#define JS_BUFF_SIZE 32 /* output buffer size */ -#define JS_RETRIES 4 /* number of retries */ -#define JS_DEF_PREC 16 /* initial precision for all axes */ - -#define JS_NUM 2 /* number of joysticks */ - -#define JS_AXES 0x0f /* bit mask for all axes */ -#define JS_BUTTONS 0xf0 /* bit mask for all buttons */ - -#define PIT_MODE 0x43 /* timer mode port */ -#define PIT_DATA 0x40 /* timer 0 data port */ -#define JS_PORT 0x201 /* joystick port */ - -#define JS_TRIGGER 0xff /* triggers one-shots */ -#define PIT_READ_TIMER 0x00 /* to read timer 0 */ - -#define DELTA(X,Y,Z) ((X)-(Y)+(((X)>=(Y))?0:Z)) /* cyclic delta */ -#define DELTA_T(X,Y) DELTA((X),(Y),(PIT_HZ/HZ)) /* for time measurement */ -#define DELTA_TX(X,Y,Z) DELTA_T((X),((Y)&0xFF)|(((Z)&0xFF)<<8)) -#define ROT(A,B,C) ((((A)<(C))&&(((B)>(A))&&((B)<(C))))||(((A)>(C))&&(((B)>(A))||((B)<(C))))) -#define GOF(X) (((X)==JS_BUFF_SIZE-1)?0:(X)+1) -#define GOFF(X) (((X)==JS_FIFO_SIZE-1)?0:(X)+1) -#define GOB(X) ((X)?(X)-1:JS_BUFF_SIZE-1) - -struct js_data { - int ahead; - int bhead; - int tail; - struct js_event buff[JS_BUFF_SIZE]; - struct js_list *list; - struct wait_queue *wait; - unsigned int exist; -}; - -struct js_axis { - int value; - struct js_corr corr; -}; - -struct js_list { - struct js_list *next; /* next-in-list pointer */ - unsigned long time; /* when the device was open */ - int tail; /* a tail for js_buff */ - char startup; -}; - -struct js_fifo { - unsigned long time; - unsigned long event; -}; - -static struct js_data jsd[JS_NUM]; /* joystick data */ -static struct timer_list js_timer; /* joystick timer */ - -static unsigned char js_fifo_head = 0; /* head of the fifo */ -static unsigned char js_fifo_tail = JS_FIFO_SIZE - 1; /* tail of the fifo */ -static struct js_fifo js_fifo[JS_FIFO_SIZE]; /* the fifo */ - -static unsigned char js_last_buttons = 0; /* last read button state */ -static unsigned long js_bh_time = 0; /* last read axis time */ -static unsigned long js_mark_time = 0; - -static unsigned char js_axes_exist; /* all axes that exist */ -static unsigned char js_buttons_exist; /* all buttons that exist */ - -static struct js_axis js_axis[4]; -static unsigned int js_buttons = 0; - -MODULE_AUTHOR("Vojtech Pavlik <vojtech@atrey.karlin.mff.cuni.cz>"); -MODULE_SUPPORTED_DEVICE("js"); -MODULE_PARM(js, "1-2b"); - -static char js[] = {0, 0}; - -/* - * get_pit() returns the immediate state of PIT0. Must be run - * with interrupts disabled. - */ - -static inline int get_pit(void) -{ - int t, flags; - - save_flags(flags); - cli(); - outb(PIT_READ_TIMER, PIT_MODE); - t = inb(PIT_DATA); - t |= (int) inb(PIT_DATA) << 8; - restore_flags(flags); - return t; -} - -/* - * count_bits() counts set bits in a byte. - */ - -static int count_bits(unsigned int c) -{ - int i = 0; - while (c) { - i += c & 1; - c >>= 1; - } - return i; -} - -/* - * js_correct() performs correction of raw joystick data. - */ - -static int js_correct(int value, struct js_corr *corr) -{ - int t; - - if (corr->type == JS_CORR_NONE) return value; - t = value > corr->coef[0] ? (value < corr->coef[1] ? 0 : value - corr->coef[1]) : value - corr->coef[0]; - - switch (corr->type) { - case JS_CORR_BROKEN: - t = t < 0 ? ((corr->coef[2] * t) >> 14) : ((corr->coef[3] * t) >> 14); - break; - default: - return 0; - } - - if (t < -32767) return -32767; - if (t > 32767) return 32767; - - return t; -} - -/* - * js_compare() compares two close axis values and decides - * whether they are "same". - */ - -static int js_compare(int x, int y, int prec) -{ - return (x < y + prec) && (y < x + prec); -} - -/* - * js_probe() probes for joysticks - */ - -inline int js_probe(void) -{ - int t; - - outb(JS_TRIGGER, JS_PORT); - t = get_pit(); - while (DELTA_T(t, get_pit()) < JS_MAXTIME); - t = inb(JS_PORT); - - if (js[0] || js[1]) { - jsd[0].exist = js[0] & ~(t & JS_AXES); - jsd[1].exist = js[1] & ~(t & JS_AXES); - } else - switch (t & JS_AXES) { - case 0x0c: jsd[0].exist = 0x33; jsd[1].exist = 0x00; break; /* joystick 0 connected */ - case 0x03: jsd[0].exist = 0xcc; jsd[1].exist = 0x00; break; /* joystick 1 connected */ - case 0x04: jsd[0].exist = 0xfb; jsd[1].exist = 0x00; break; /* 3-axis joystick connected */ - case 0x00: jsd[0].exist = 0x33; jsd[1].exist = 0xcc; break; /* joysticks 0 and 1 connected */ - default: jsd[0].exist = 0x00; jsd[1].exist = 0x00; return -1; /* no joysticks */ - } - - js_axes_exist = (jsd[0].exist | jsd[1].exist) & JS_AXES; - js_buttons_exist = (jsd[0].exist | jsd[1].exist) & JS_BUTTONS; - - return 0; -} - -/* - * js_do_timer() controls the action by adding entries to the event - * fifo each time a button changes its state or axis valid time - * expires. - */ - -static void js_do_timer(unsigned long data) -{ - int t = ~inb(JS_PORT) & js_buttons_exist; - if ((js_last_buttons != t) && (js_fifo_head != js_fifo_tail)) { - js_fifo[js_fifo_head].event = js_last_buttons = t; - js_fifo[js_fifo_head].time = jiffies; - js_fifo_head++; - if (js_fifo_head == JS_FIFO_SIZE) js_fifo_head = 0; - if (!js_mark_time) { - js_mark_time = jiffies; - mark_bh(JS_BH); - } - } - else - if ((jiffies > js_bh_time + JS_BH_MAX_PERIOD) && !js_mark_time) { - js_mark_time = jiffies; - mark_bh(JS_BH); - } - js_timer.expires = jiffies + JS_TIMER_PERIOD; - add_timer(&js_timer); -} - - -/* - * Put an event in the buffer. This requires additional queue processing - * done by js_sync_buff, otherwise the buffer will be corrupted. - */ - -static void js_add_event(int i, __u32 time, __u8 type, __u8 number, __u16 value) -{ - int ahead = jsd[i].ahead++; - jsd[i].buff[ahead].time = time; - jsd[i].buff[ahead].type = type; - jsd[i].buff[ahead].number = number; - jsd[i].buff[ahead].value = value; - if (jsd[i].ahead == JS_BUFF_SIZE) jsd[i].ahead=0; -} - -/* - * This checks for all owerflows caused by recent additions to the buffer. - * It does anything only if some processes are reading the data too slowly. - */ - -static void js_sync_buff(void) -{ - int i; - - for (i = 0; i < JS_NUM; i++) - if (jsd[i].list) - if (jsd[i].bhead != jsd[i].ahead) { - if (ROT(jsd[i].bhead, jsd[i].tail, jsd[i].ahead) || (jsd[i].tail == jsd[i].bhead)) { - struct js_list *curl; - curl = jsd[i].list; - while (curl) { - if (ROT(jsd[i].bhead, curl->tail, jsd[i].ahead) || (curl->tail == jsd[i].bhead)) { - curl->tail = jsd[i].ahead; - curl->startup = jsd[i].exist; - } - curl = curl->next; - } - jsd[i].tail = jsd[i].ahead; - } - jsd[i].bhead = jsd[i].ahead; - wake_up_interruptible(&jsd[i].wait); - } -} - -/* - * js_do_bh() does the main processing and adds events to output buffers. - */ - -static void js_do_bh(void) -{ - - int i, j, k; - unsigned int t; - - if (jiffies > js_bh_time + JS_BH_MIN_PERIOD) { - - unsigned int old_axis[4]; - unsigned int t_low, t_high; - unsigned int flags, joy_state; - unsigned int t1l, t1h, jsm; - unsigned char jss; - unsigned char again; - unsigned char retries = 0; - - for (i = 0; i < 4; i++) - old_axis[i] = js_axis[i].value; - - do { - i = 0; - again = 0; - t_low = 0; - t_high = 0; - joy_state = JS_AXES; - -/* - * Measure the axes. - */ - - save_flags(flags); - cli(); /* no interrupts */ - outb(JS_TRIGGER, JS_PORT); /* trigger one-shots */ - outb(PIT_READ_TIMER, PIT_MODE); /* read timer */ - t = (t1l = inb(PIT_DATA)) | - (t1h = inb(PIT_DATA)) << 8; - restore_flags(flags); - - do { - jss = inb(JS_PORT); - if ((jss ^ joy_state) & js_axes_exist) { - t_low = (t_low << 8) | t1l; - t_high = (t_high << 8) | t1h; - joy_state = (joy_state << 8) | jss; - i++; - } - - cli(); - outb(PIT_READ_TIMER, PIT_MODE); - t1l = inb(PIT_DATA); - t1h = inb(PIT_DATA); - restore_flags(flags); - - } while ((jss & js_axes_exist) && (DELTA_TX(t, t1l, t1h) < JS_MAXTIME)); - -/* - * Process the gathered axis data in joy_state. - */ - - joy_state ^= ((joy_state >> 8) | 0xff000000L); /* More magic */ - - for (; i > 0; i--) { - for (j = 0; j < 4; j++) - if (joy_state & js_axes_exist & (1 << j)) { - jsm = DELTA_TX(t, t_low, t_high); - if (!js_compare(jsm, js_axis[j].value, js_axis[j].corr.prec)) { - if (jsm < js_axis[j].value || !retries) - js_axis[j].value = jsm; - again = 1; - } - } - joy_state = joy_state >> 8; - t_low = t_low >> 8; - t_high = t_high >> 8; - } - - } while (retries++ < JS_RETRIES && again); - -/* - * Check if joystick lost. - */ - - for (i = 0; i < JS_NUM; i++) { - - if (jsd[i].exist && ((jss & jsd[i].exist & JS_AXES) == (jsd[i].exist & JS_AXES))) { - printk(KERN_WARNING "js%d: joystick lost.\n", i); - js_buttons_exist &= ~jsd[i].exist; - js_axes_exist &= ~jsd[i].exist; - jsd[i].exist = 0; - wake_up_interruptible(&jsd[i].wait); - } - - if ((jss & jsd[i].exist & JS_AXES)) { - printk(KERN_WARNING "js%d: joystick broken. Check cables.\n", i); - } - - } - -/* - * Put changed axes into output buffer. - */ - - if (retries > 1) - for (i = 0; i < JS_NUM; i++) - if (jsd[i].list) { - k = 0; - for (j = 0; j < 4; j++) - if ((1 << j) & jsd[i].exist) { - if ((t = js_correct(js_axis[j].value, &js_axis[j].corr)) != - js_correct(old_axis[j], &js_axis[j].corr)) - js_add_event(i, js_mark_time, JS_EVENT_AXIS, k, t); - k++; - } - } - js_bh_time = jiffies; - } - js_mark_time = 0; - -/* - * And now process the button fifo. - */ - - while (js_fifo_head != (t = GOFF(js_fifo_tail))) { - for (i = 0; i < JS_NUM; i++) - if (jsd[i].list) { - k = 0; - for (j = 4; j < 8; j++) - if ((1 << j) & jsd[i].exist) { - if ((1 << j) & (js_buttons ^ js_fifo[t].event)) - js_add_event(i, js_fifo[t].time, JS_EVENT_BUTTON, k, (js_fifo[t].event >> j) & 1); - k++; - } - } - js_buttons = js_fifo[js_fifo_tail = t].event; - } - -/* - * Synchronize the buffer. - */ - - js_sync_buff(); - -} - -/* - * js_lseek() just returns with error. - */ - -static loff_t js_lseek(struct file *file, loff_t offset, int origin) -{ - return -ESPIPE; -} - -/* - * js_read() copies one or more entries from jsd[].buff to user - * space. - */ - -static ssize_t js_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); - struct wait_queue wait = { current, NULL }; - struct js_list *curl = file->private_data; - struct js_event *buff = (void *) buf; - unsigned long blocks = count / sizeof(struct js_event); - unsigned long i = 0, j; - int t, u = curl->tail; - int retval = 0; - -/* - * Check user data. - */ - - if (MAJOR(file->f_dentry->d_inode->i_rdev) != JOYSTICK_MAJOR) - return -EINVAL; - if (file->f_pos < 0) - return -EINVAL; - if (!blocks) - return -EINVAL; - if (!curl) - return -EINVAL; - - if (minor > JS_NUM) - return -ENODEV; - if (!jsd[minor].exist) - return -ENODEV; - -/* - * Handle (non)blocking i/o. - */ - - - if ((GOF(curl->tail) == jsd[minor].ahead && !curl->startup && count != sizeof(struct JS_DATA_TYPE)) - || (curl->startup && !js_bh_time)) { - - add_wait_queue(&jsd[minor].wait, &wait); - current->state = TASK_INTERRUPTIBLE; - - while ((GOF(curl->tail) == jsd[minor].ahead && !curl->startup && count != sizeof(struct JS_DATA_TYPE)) - || (curl->startup && !js_bh_time)) { - - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - if (!jsd[minor].exist) { - retval = -ENODEV; - break; - } - } - current->state = TASK_RUNNING; - remove_wait_queue(&jsd[minor].wait, &wait); - } - - if (retval) return retval; - -/* - * Do the i/o. - */ - if (count != sizeof(struct JS_DATA_TYPE)) { - - if (curl->startup) { - struct js_event tmpevent; -/* - * Initial button state. - */ - - t = 0; - for (j = 0; j < 4 && (i < blocks) && !retval; j++) - if (jsd[minor].exist & (1 << j)) { - if (curl->startup & (1 << j)) { - tmpevent.type = JS_EVENT_AXIS | JS_EVENT_INIT; - tmpevent.number = t; - tmpevent.value = js_correct(js_axis[j].value, &js_axis[j].corr); - if (copy_to_user(&buff[i], &tmpevent, sizeof(struct js_event))) - retval = -EFAULT; - if (put_user((__u32)((jiffies - curl->time) * (1000/HZ)), &buff[i].time)) - retval = -EFAULT; - curl->startup &= ~(1 << j); - i++; - } - t++; - } - -/* - * Initial axis state. - */ - - t = 0; - for (j = 4; j < 8 && (i < blocks) && !retval; j++) - if (jsd[minor].exist & (1 << j)) { - if (curl->startup & (1 << j)) { - tmpevent.type = JS_EVENT_BUTTON | JS_EVENT_INIT; - tmpevent.number = t; - tmpevent.value = (js_buttons >> j) & 1; - if (copy_to_user(&buff[i], &tmpevent, sizeof(struct js_event))) - retval = -EFAULT; - if (put_user((__u32)((jiffies - curl->time) * (1000/HZ)), &buff[i].time)) - retval = -EFAULT; - curl->startup &= ~(1 << j); - i++; - } - t++; - } - } - -/* - * Buffer data. - */ - - while ((jsd[minor].ahead != (t = GOF(curl->tail))) && (i < blocks) && !retval) { - if (copy_to_user(&buff[i], &jsd[minor].buff[t], sizeof(struct js_event))) - retval = -EFAULT; - if (put_user((__u32)((jsd[minor].buff[t].time - curl->time) * (1000/HZ)), &buff[i].time)) - retval = -EFAULT; - curl->tail = t; - i++; - } - - } - - else - -/* - * Handle version 0.x compatibility. - */ - - { - struct JS_DATA_TYPE *bufo = (void *) buf; - int buttons = 0; - - while (~jsd[minor].exist & (1<<i)) i++; - copy_to_user(&bufo->x, &js_axis[i].value, sizeof(int)); - - i++; - while (~jsd[minor].exist & (1<<i)) i++; - copy_to_user(&bufo->y, &js_axis[i].value, sizeof(int)); - - i = 0; - for (j = 4; j < 8; j++) - if ((1 << j) & jsd[minor].exist) - buttons |= (!!(js_last_buttons & (1 << j))) << (i++); - copy_to_user(&bufo->buttons, &buttons, sizeof(int)); - - curl->startup = 0; - curl->tail = GOB(jsd[minor].ahead); - retval = sizeof(struct JS_DATA_TYPE); - } - -/* - * Check main tail and move it. - */ - - if (u == jsd[minor].tail) { - t = curl->tail; - curl = jsd[minor].list; - while (curl && curl->tail != jsd[minor].tail) { - if (ROT(jsd[minor].ahead, t, curl->tail) || - (jsd[minor].ahead == curl->tail)) t = curl->tail; - curl = curl->next; - } - if (!curl) jsd[minor].tail = t; - } - - return retval ? retval : i*sizeof(struct js_event); -} - -/* - * js_poll() does select() support. - */ - -static unsigned int js_poll(struct file *file, poll_table *wait) -{ - struct js_list *curl; - unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); - curl = file->private_data; - - poll_wait(file, &jsd[minor].wait, wait); - if (GOF(curl->tail) != jsd[minor].ahead) - return POLLIN | POLLRDNORM; - return 0; -} - -/* - * js_ioctl handles misc ioctl calls. - */ - -static int js_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ - unsigned int minor = MINOR(inode->i_rdev); - int i, j; - - if (MAJOR(inode->i_rdev) != JOYSTICK_MAJOR) - return -EINVAL; - if (minor > JS_NUM) - return -ENODEV; - if (!jsd[minor].exist) - return -ENODEV; - - switch (cmd) { - case JSIOCGVERSION: - if(put_user(JS_VERSION, (__u32 *) arg)) return -EFAULT; - break; - case JSIOCGAXES: - if(put_user(count_bits(jsd[minor].exist & JS_AXES), (__u8 *) arg)) return -EFAULT; - break; - case JSIOCGBUTTONS: - if(put_user(count_bits(jsd[minor].exist & JS_BUTTONS), (__u8 *) arg)) return -EFAULT; - break; - case JSIOCSCORR: - j = 0; - for (i = 0; i < 4; i++) - if ((1 << i) & jsd[minor].exist) { - if (copy_from_user(&js_axis[i].corr, (void *) arg + j * sizeof(struct js_corr), - sizeof(struct js_corr))) return -EFAULT; - j++; - } - js_bh_time = 0; - break; - case JSIOCGCORR: - j = 0; - for (i = 0; i < 4; i++) - if ((1 << i) & jsd[minor].exist) { - if (copy_to_user((void *) arg + j * sizeof(struct js_corr), &js_axis[i].corr, - sizeof(struct js_corr))) return -EFAULT; - j++; - } - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * js_open() performs necessary initialization and adds - * an entry to the linked list. - */ - -static int js_open(struct inode *inode, struct file *file) -{ - unsigned int minor = MINOR(inode->i_rdev); - struct js_list *curl; - int t; - - if (MAJOR(inode->i_rdev) != JOYSTICK_MAJOR) - return -EINVAL; - if (minor > JS_NUM) - return -ENODEV; - if (!jsd[minor].exist) { - js_probe(); - if (jsd[minor].exist) printk(KERN_INFO "js%d: %d-axis %d-button joystick at %#x\n", - minor, count_bits(jsd[minor].exist & JS_AXES), count_bits(jsd[minor].exist & JS_BUTTONS), JS_PORT); - else return -ENODEV; - } - - MOD_INC_USE_COUNT; - - if (!jsd[0].list && !jsd[1].list) { - js_timer.expires = jiffies + JS_TIMER_PERIOD; - add_timer(&js_timer); - } - - curl = jsd[minor].list; - jsd[minor].list = kmalloc(sizeof(struct js_list), GFP_KERNEL); - jsd[minor].list->next = curl; - jsd[minor].list->startup = jsd[minor].exist; - jsd[minor].list->tail = t = GOB(jsd[minor].ahead); - jsd[minor].list->time = jiffies; - - file->private_data = jsd[minor].list; - - return 0; -} - -/* - * js_release() removes an entry from list and deallocates memory - * used by it. - */ - -static int js_release(struct inode *inode, struct file *file) -{ - unsigned int minor = MINOR(inode->i_rdev); - struct js_list **curp, *curl; - int t; - - curp = &jsd[minor].list; - curl = file->private_data; - - while (*curp && (*curp != curl)) curp = &((*curp)->next); - *curp = (*curp)->next; - - if (jsd[minor].list) { - if (curl->tail == jsd[minor].tail) { - curl = jsd[minor].list; - t = curl->tail; - while (curl && curl->tail != jsd[minor].tail) { - if (ROT(jsd[minor].ahead, t, curl->tail) || - (jsd[minor].ahead == curl->tail)) t = curl->tail; - curl = curl->next; - } - if (!curl) jsd[minor].tail = t; - } - } - - kfree(file->private_data); - if (!jsd[0].list && !jsd[1].list) del_timer(&js_timer); - - MOD_DEC_USE_COUNT; - return 0; -} - -/* - * The operations structure. - */ - -static struct file_operations js_fops = -{ - js_lseek, /* js_lseek */ - js_read, /* js_read */ - NULL, /* js_write */ - NULL, /* js_readdir */ - js_poll, /* js_poll */ - js_ioctl, /* js_ioctl */ - NULL, /* js_mmap */ - js_open, /* js_open */ - NULL, /* js_flush */ - js_release, /* js_release */ - NULL /* js_sync */ -}; - -/* - * js_setup() parses kernel command line parametres. - */ - -#ifndef MODULE -__initfunc(void js_setup(char *str, int *ints)) - -{ - js[0] = ((ints[0] > 0) ? ints[1] : 0 ); - js[1] = ((ints[0] > 1) ? ints[2] : 0 ); -} -#endif - -/* - * js_init() registres the driver and calls the probe function. - * also initializes some crucial variables. - */ - -#ifdef MODULE -int init_module(void) -#else -__initfunc(int js_init(void)) -#endif -{ - int i; - - if (check_region(JS_PORT, 1)) { - printk(KERN_ERR "js: port %#x already in use\n", JS_PORT); - return -EBUSY; - } - - if (js_probe() < 0) { - printk(KERN_INFO "js: no joysticks found\n"); - return -ENODEV; - } - - if (register_chrdev(JOYSTICK_MAJOR, "js", &js_fops)) { - printk(KERN_ERR "js: unable to get major %d for joystick\n", JOYSTICK_MAJOR); - return -EBUSY; - } - - for (i = 0; i < JS_NUM; i++) { - if (jsd[i].exist) printk(KERN_INFO "js%d: %d-axis %d-button joystick at %#x\n", - i, count_bits(jsd[i].exist & JS_AXES), count_bits(jsd[i].exist & JS_BUTTONS), JS_PORT); - jsd[i].ahead = jsd[i].bhead = 0; - jsd[i].tail = JS_BUFF_SIZE - 1; - jsd[i].list = NULL; - jsd[i].wait = NULL; - memset(jsd[i].buff, 0, JS_BUFF_SIZE * sizeof(struct js_event)); - } - - for (i = 0; i < 4; i++) { - js_axis[i].corr.type = JS_CORR_NONE; - js_axis[i].corr.prec = JS_DEF_PREC; - } - - request_region(JS_PORT, 1, "js"); - init_bh(JS_BH, &js_do_bh); - enable_bh(JS_BH); - init_timer(&js_timer); - js_timer.function = js_do_timer; - - return 0; -} - -/* - * cleanup_module() handles module removal. - */ - -#ifdef MODULE -void cleanup_module(void) -{ - if (MOD_IN_USE) - printk(KERN_NOTICE "js: device busy, remove delayed\n"); - else { - del_timer(&js_timer); - disable_bh(JS_BH); - if (unregister_chrdev(JOYSTICK_MAJOR, "js")) - printk(KERN_ERR "js: module cleanup failed\n"); - release_region(JS_PORT, 1); - } -} -#endif |