📄 joystick.c
字号:
{ struct JS_DATA_TYPE data; data.buttons = jd->new.buttons[0]; data.x = jd->num_axes < 1 ? 0 : ((js_correct(jd->new.axes[0], &jd->corr[0]) / 256) + 128) >> js_comp_glue.JS_CORR.x; data.y = jd->num_axes < 2 ? 0 : ((js_correct(jd->new.axes[1], &jd->corr[1]) / 256) + 128) >> js_comp_glue.JS_CORR.y;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) retval = copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0;#else if (!(retval = verify_area(VERIFY_WRITE, buf, sizeof(struct JS_DATA_TYPE)))) { memcpy_tofs(buf, &data, sizeof(struct JS_DATA_TYPE)); }#endif curl->startup = 0; curl->tail = GOB(jd->bhead); if (!retval) retval = sizeof(struct JS_DATA_TYPE); }/* * Check main tail and move it. */ if (orig_tail == jd->tail) { new_tail = curl->tail; curl = jd->list; while (curl != NULL && curl->tail != jd->tail) { if (ROT(jd->bhead, new_tail, curl->tail) || (jd->bhead == curl->tail)) new_tail = curl->tail; curl = curl->next; } if (curl == NULL) jd->tail = new_tail; } spin_unlock_irqrestore(&js_lock, flags); return retval ? retval : written * sizeof(struct js_event);}/* * js_poll() does select() support. */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)static unsigned int js_poll(struct file *file, poll_table *wait){ struct js_list *curl = file->private_data; unsigned long flags; int retval = 0; poll_wait(file, &curl->dev->wait, wait); spin_lock_irqsave(&js_lock, flags); if (GOF(curl->tail) != curl->dev->bhead || curl->startup < curl->dev->num_axes + curl->dev->num_buttons) retval = POLLIN | POLLRDNORM; spin_unlock_irqrestore(&js_lock, flags); return retval;}#elsestatic int js_select(struct inode *inode, struct file *file, int sel_type, select_table *wait){ struct js_list *curl = file->private_data; if (sel_type == SEL_IN) { if (GOF(curl->tail) != curl->dev->bhead) return 1; select_wait(&curl->dev->wait, wait); } return 0;}#endif/* * js_ioctl handles misc ioctl calls. */static int js_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct js_list *curl; struct js_dev *jd; int len; curl = file->private_data; jd = curl->dev;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) switch (cmd) {/* * 0.x compatibility */ case JS_SET_CAL: return copy_from_user(&js_comp_glue.JS_CORR, (struct JS_DATA_TYPE *) arg, sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; case JS_GET_CAL: return copy_to_user((struct JS_DATA_TYPE *) arg, &js_comp_glue.JS_CORR, sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; case JS_SET_TIMEOUT: return get_user(js_comp_glue.JS_TIMEOUT, (int *) arg); case JS_GET_TIMEOUT: return put_user(js_comp_glue.JS_TIMEOUT, (int *) arg); case JS_SET_TIMELIMIT: return get_user(js_comp_glue.JS_TIMELIMIT, (long *) arg); case JS_GET_TIMELIMIT: return put_user(js_comp_glue.JS_TIMELIMIT, (long *) arg); case JS_SET_ALL: return copy_from_user(&js_comp_glue, (struct JS_DATA_SAVE_TYPE *) arg, sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; case JS_GET_ALL: return copy_to_user((struct JS_DATA_SAVE_TYPE *) arg, &js_comp_glue, sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0;/* * 1.x ioctl calls */ case JSIOCGVERSION: return put_user(JS_VERSION, (__u32 *) arg); case JSIOCGAXES: return put_user(jd->num_axes, (__u8 *) arg); case JSIOCGBUTTONS: return put_user(jd->num_buttons, (__u8 *) arg); case JSIOCSCORR: return copy_from_user(jd->corr, (struct js_corr *) arg, sizeof(struct js_corr) * jd->num_axes) ? -EFAULT : 0; case JSIOCGCORR: return copy_to_user((struct js_corr *) arg, jd->corr, sizeof(struct js_corr) * jd->num_axes) ? -EFAULT : 0; default: if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) { len = strlen(jd->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); if (copy_to_user((char *) arg, jd->name, len)) return -EFAULT; return len; } }#else switch (cmd) {/* * 0.x compatibility */ case JS_SET_CAL: if (verify_area(VERIFY_READ, (struct JS_DATA_TYPE *) arg, sizeof(struct JS_DATA_TYPE))) return -EFAULT; memcpy_fromfs(&js_comp_glue.JS_CORR, (struct JS_DATA_SAVE_TYPE *) arg, sizeof(struct JS_DATA_TYPE)); return 0; case JS_GET_CAL: if (verify_area(VERIFY_WRITE, (struct JS_DATA_TYPE *) arg, sizeof(struct JS_DATA_TYPE))) return -EFAULT; memcpy_tofs((struct JS_DATA_SAVE_TYPE *) arg, &js_comp_glue.JS_CORR, sizeof(struct JS_DATA_TYPE)); return 0; case JS_SET_TIMEOUT: if (verify_area(VERIFY_READ, (int *) arg, sizeof(int))) return -EFAULT; js_comp_glue.JS_TIMEOUT = get_user((int *) arg); return 0; case JS_GET_TIMEOUT: if (verify_area(VERIFY_WRITE, (int *) arg, sizeof(int))) return -EFAULT; put_user(js_comp_glue.JS_TIMEOUT, (int *) arg); return 0; case JS_SET_TIMELIMIT: if (verify_area(VERIFY_READ, (long *) arg, sizeof(long))) return -EFAULT; js_comp_glue.JS_TIMELIMIT = get_user((long *) arg); return 0; case JS_GET_TIMELIMIT: if (verify_area(VERIFY_WRITE, (long *) arg, sizeof(long))) return -EFAULT; put_user(js_comp_glue.JS_TIMELIMIT, (long *) arg); return 0; case JS_SET_ALL: if (verify_area(VERIFY_READ, (struct JS_DATA_SAVE_TYPE *) arg, sizeof(struct JS_DATA_SAVE_TYPE))) return -EFAULT; memcpy_fromfs(&js_comp_glue, (struct JS_DATA_SAVE_TYPE *) arg, sizeof(struct JS_DATA_SAVE_TYPE)); return 0; case JS_GET_ALL: if (verify_area(VERIFY_WRITE, (struct JS_DATA_SAVE_TYPE *) arg, sizeof(struct JS_DATA_SAVE_TYPE))) return -EFAULT; memcpy_tofs((struct JS_DATA_SAVE_TYPE *) arg, &js_comp_glue, sizeof(struct JS_DATA_SAVE_TYPE)); return 0;/* * 1.x ioctl calls */ case JSIOCGVERSION: if (verify_area(VERIFY_WRITE, (__u32 *) arg, sizeof(__u32))) return -EFAULT; put_user(JS_VERSION, (__u32 *) arg); return 0; case JSIOCGAXES: if (verify_area(VERIFY_WRITE, (__u8 *) arg, sizeof(__u8))) return -EFAULT; put_user(jd->num_axes, (__u8 *) arg); return 0; case JSIOCGBUTTONS: if (verify_area(VERIFY_WRITE, (__u8 *) arg, sizeof(__u8))) return -EFAULT; put_user(jd->num_buttons, (__u8 *) arg); return 0; case JSIOCSCORR: if (verify_area(VERIFY_READ, (struct js_corr *) arg, sizeof(struct js_corr) * jd->num_axes)) return -EFAULT; memcpy_fromfs(jd->corr, (struct js_corr *) arg, sizeof(struct js_corr) * jd->num_axes); return 0; case JSIOCGCORR: if (verify_area(VERIFY_WRITE, (struct js_corr *) arg, sizeof(struct js_corr) * jd->num_axes)) return -EFAULT; memcpy_tofs((struct js_corr *) arg, jd->corr, sizeof(struct js_corr) * jd->num_axes); return 0; default: if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) { len = strlen(jd->name) + 1; if (verify_area(VERIFY_WRITE, (char *) arg, len)) return -EFAULT; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); memcpy_tofs((char *) arg, jd->name, len); return len; } }#endif return -EINVAL;}/* * js_open() performs necessary initialization and adds * an entry to the linked list. */static int js_open(struct inode *inode, struct file *file){ struct js_list *curl, *new; struct js_dev *jd = js_dev; int i = MINOR(inode->i_rdev); unsigned long flags; int result; if (MAJOR(inode->i_rdev) != JOYSTICK_MAJOR) return -EINVAL; spin_lock_irqsave(&js_lock, flags); while (i > 0 && jd != NULL) { jd = jd->next; i--; } spin_unlock_irqrestore(&js_lock, flags); if (jd == NULL) return -ENODEV; if ((result = jd->open(jd))) return result; MOD_INC_USE_COUNT; if (!js_use_count++) js_do_timer(0); if ((new = kmalloc(sizeof(struct js_list), GFP_KERNEL)) != NULL) { spin_lock_irqsave(&js_lock, flags); curl = jd->list; jd->list = new; jd->list->next = curl; jd->list->dev = jd; jd->list->startup = 0; jd->list->tail = GOB(jd->bhead); file->private_data = jd->list; spin_unlock_irqrestore(&js_lock, flags); } else { result = -ENOMEM; } return result;}/* * js_release() removes an entry from list and deallocates memory * used by it. */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)static int js_release(struct inode *inode, struct file *file)#elsestatic void js_release(struct inode *inode, struct file *file)#endif{ struct js_list *curl = file->private_data; struct js_dev *jd = curl->dev; struct js_list **curp = &jd->list; int new_tail; unsigned long flags; spin_lock_irqsave(&js_lock, flags); while (*curp && (*curp != curl)) curp = &((*curp)->next); *curp = (*curp)->next; if (jd->list != NULL) if (curl->tail == jd->tail) { curl = jd->list; new_tail = curl->tail; while (curl != NULL && curl->tail != jd->tail) { if (ROT(jd->bhead, new_tail, curl->tail) || (jd->bhead == curl->tail)) new_tail = curl->tail; curl = curl->next; } if (!curl) jd->tail = new_tail; } spin_unlock_irqrestore(&js_lock, flags); kfree(file->private_data); if (!--js_use_count) del_timer(&js_timer); MOD_DEC_USE_COUNT; jd->close(jd);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) return 0;#endif}/* * js_dump_mem() dumps all data structures in memory. * It's used for debugging only. */#if 0static void js_dump_mem(void){ struct js_port *curp = js_port; struct js_dev *curd = js_dev; int i; printk(",--- Dumping Devices:\n"); printk("| js_dev = %x\n", (int) js_dev); while (curd != NULL) { printk("| %s-device %x, next %x axes %d, buttons %d, port %x - %#x\n", curd->next ? "|":"`", (int) curd, (int) curd->next, curd->num_axes, curd->num_buttons, (int) curd->port, curd->port->io); curd = curd->next; } printk(">--- Dumping ports:\n"); printk("| js_port = %x\n", (int) js_port); while (curp != NULL) { printk("| %s-port %x, next %x, io %#x, devices %d\n", curp->next ? "|":"`", (int) curp, (int) curp->next, curp->io, curp->ndevs); for (i = 0; i < curp->ndevs; i++) { curd = curp->devs[i]; if (curd) printk("| %s %s-device %x, next %x axes %d, buttons %d, port %x\n", curp->next ? "|":" ", (i < curp->ndevs-1) ? "|":"`", (int) curd, (int) curd->next, curd->num_axes, curd->num_buttons, (int) curd->port); else printk("| %s %s-device %x, not there\n", curp->next ? "|":" ", (i < curp->ndevs-1) ? "|":"`", (int) curd); } curp = curp->next; } printk("`--- Done\n");}#endifstruct js_port *js_register_port(struct js_port *port, void *info, int devs, int infos, js_read_func read){ struct js_port **ptrp = &js_port; struct js_port *curp; void *all; int i; unsigned long flags; if ((all = kmalloc(sizeof(struct js_port) + 4 * devs * sizeof(void*) + infos, GFP_KERNEL)) == NULL) return NULL; curp = all; curp->next = NULL; curp->prev = port; curp->read = read; curp->ndevs = devs; curp->devs = all += sizeof(struct js_port); for (i = 0; i < devs; i++) curp->devs[i] = NULL; curp->axes = all += devs * sizeof(void*); curp->buttons = (void*) all += devs * sizeof(void*); curp->corr = all += devs * sizeof(void*); if (infos) { curp->info = all += devs * sizeof(void*); memcpy(curp->info, info, infos); } else { curp->info = NULL; } spin_lock_irqsave(&js_lock, flags); while (*ptrp != NULL) ptrp=&((*ptrp)->next); *ptrp = curp; spin_unlock_irqrestore(&js_lock, flags); return curp;}struct js_port *js_unregister_port(struct js_port *port){ struct js_port **curp = &js_port; struct js_port *prev; unsigned long flags; spin_lock_irqsave(&js_lock, flags); while (*curp != NULL && (*curp != port)) curp = &((*curp)->next); *curp = (*curp)->next; spin_unlock_irqrestore(&js_lock, flags); prev = port->prev; kfree(port); return prev;}int js_register_device(struct js_port *port, int number, int axes, int buttons, char *name, js_ops_func open, js_ops_func close){ struct js_dev **ptrd = &js_dev; struct js_dev *curd; void *all; int i = 0; unsigned long flags; if ((all = kmalloc(sizeof(struct js_dev) + 2 * axes * sizeof(int) + 2 * (((buttons - 1) >> 5) + 1) * sizeof(int) + axes * sizeof(struct js_corr) + strlen(name) + 1, GFP_KERNEL)) == NULL) return -1; curd = all; curd->next = NULL; curd->list = NULL; curd->port = port; curd->wait = NULL; curd->open = open; curd->close = close; curd->ahead = 0; curd->bhead = 0; curd->tail = JS_BUFF_SIZE - 1; curd->num_axes = axes; curd->num_buttons = buttons; curd->cur.axes = all += sizeof(struct js_dev); curd->cur.buttons = all += axes * sizeof(int); curd->new.axes = all += (((buttons - 1) >> 5) + 1) * sizeof(int); curd->new.buttons = all += axes * sizeof(int); curd->corr = all += (((buttons -1 ) >> 5) + 1) * sizeof(int); curd->name = all += axes * sizeof(struct js_corr); strcpy(curd->name, name); port->devs[number] = curd; port->axes[number] = curd->new.axes; port->buttons[number] = curd->new.buttons; port->corr[number] = curd->corr; spin_lock_irqsave(&js_lock, flags); while (*ptrd != NULL) { ptrd=&(*ptrd)->next; i++; } *ptrd = curd; spin_unlock_irqrestore(&js_lock, flags); return i;}void js_unregister_device(struct js_dev *dev){ struct js_dev **curd = &js_dev; unsigned long flags; spin_lock_irqsave(&js_lock, flags); while (*curd != NULL && (*curd != dev)) curd = &((*curd)->next); *curd = (*curd)->next; spin_unlock_irqrestore(&js_lock, flags); kfree(dev);}/* * The operations structure. */static struct file_operations js_fops ={ read: js_read,#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) poll: js_poll,#else select: js_select,#endif ioctl: js_ioctl, open: js_open, release: js_release,};/* * js_init() registers the driver and calls the probe function. * also initializes some crucial variables. */#ifdef MODULEint init_module(void)#elseint __init js_init(void)#endif{ int result; js_setup_time(); if (register_chrdev(JOYSTICK_MAJOR, "js", &js_fops)) { printk(KERN_ERR "js: unable to get major %d for joystick\n", JOYSTICK_MAJOR); return -EBUSY; } spin_lock_init(&js_lock); init_timer(&js_timer); js_timer.function = js_do_timer; js_timer.data = 1; memset(&js_comp_glue, 0, sizeof(struct JS_DATA_SAVE_TYPE)); js_comp_glue.JS_TIMEOUT = JS_DEF_TIMEOUT; js_comp_glue.JS_TIMELIMIT = JS_DEF_TIMELIMIT;#ifdef MODULE result = 0;#else result = -ENODEV;#ifdef CONFIG_JOY_LIGHTNING if (!js_l4_init()) result = 0;#endif#ifdef CONFIG_JOY_SIDEWINDER if (!js_sw_init()) result = 0;#endif#ifdef CONFIG_JOY_ASSASIN if (!js_as_init()) result = 0;#endif#ifdef CONFIG_JOY_LOGITECH if (!js_lt_init()) result = 0;#endif#ifdef CONFIG_JOY_THRUSTMASTER if (!js_tm_init()) result = 0;#endif#ifdef CONFIG_JOY_GRAVIS if (!js_gr_init()) result = 0;#endif#ifdef CONFIG_JOY_ANALOG if (!js_an_init()) result = 0;#endif#ifdef CONFIG_JOY_CONSOLE if (!js_console_init()) result = 0;#endif#ifdef CONFIG_JOY_DB9 if (!js_db9_init()) result = 0;#endif#ifdef CONFIG_JOY_AMIGA if (!js_am_init()) result = 0;#endif if (result) printk(KERN_ERR "js: no joysticks found\n");#endif return result;}/* * cleanup_module() handles module removal. */#ifdef MODULEvoid cleanup_module(void){ del_timer(&js_timer); if (unregister_chrdev(JOYSTICK_MAJOR, "js")) printk(KERN_ERR "js: can't unregister device\n");}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -