📄 ezusb.c
字号:
struct async *as = NULL; void *data = NULL; unsigned int pipe; int ret; if (ab->len > PAGE_SIZE) return -EINVAL; if ((ab->ep & ~0x80) >= 16) return -EINVAL; if (ab->ep & 0x80) { pipe = usb_rcvbulkpipe(ez->usbdev, ab->ep & 0x7f); if (ab->len > 0 && !access_ok(VERIFY_WRITE, ab->data, ab->len)) return -EFAULT; } else pipe = usb_sndbulkpipe(ez->usbdev, ab->ep & 0x7f); if (!usb_maxpacket(ez->usbdev, pipe, !(ab->ep & 0x80))) return -EINVAL; if (ab->len > 0 && !(data = kmalloc(ab->len, GFP_KERNEL))) return -ENOMEM; if (!(as = alloc_async(0))) { if (data) kfree(data); return -ENOMEM; } INIT_LIST_HEAD(&as->asynclist); as->ez = ez; as->userdata = ab->data; as->datalen = ab->len; as->context = ab->context; as->urb.dev = ez->usbdev; as->urb.pipe = pipe; as->urb.transfer_flags = 0; as->urb.transfer_buffer = data; as->urb.transfer_buffer_length = ab->len; as->urb.context = as; as->urb.complete = (usb_complete_t)async_completed; if (ab->len > 0 && !(ab->ep & 0x80)) { if (copy_from_user(data, ab->data, ab->len)) { free_async(as); return -EFAULT; } as->userdata = NULL; /* no need to copy back at completion */ } async_newpending(as); if ((ret = usb_submit_urb(&as->urb))) { printk(KERN_DEBUG "ezusb: bulk: usb_submit_urb returned %d\n", ret); async_removepending(as); free_async(as); return -EINVAL; /* return ret; */ } return 0;}static int ezusb_requestiso(struct ezusb *ez, struct ezusb_asynciso *ai, unsigned char *cmd){ struct async *as; void *data = NULL; unsigned int maxpkt, pipe, dsize, totsize, i, j; int ret; if ((ai->ep & ~0x80) >= 16 || ai->framecnt < 1 || ai->framecnt > 128) return -EINVAL; if (ai->ep & 0x80) pipe = usb_rcvisocpipe(ez->usbdev, ai->ep & 0x7f); else pipe = usb_sndisocpipe(ez->usbdev, ai->ep & 0x7f); if (!(maxpkt = usb_maxpacket(ez->usbdev, pipe, !(ai->ep & 0x80)))) return -EINVAL; dsize = maxpkt * ai->framecnt;//printk(KERN_DEBUG "ezusb: iso: dsize %d\n", dsize); if (dsize > 65536) return -EINVAL; if (ai->ep & 0x80) if (dsize > 0 && !access_ok(VERIFY_WRITE, ai->data, dsize)) return -EFAULT; if (dsize > 0 && !(data = kmalloc(dsize, GFP_KERNEL))) { printk("dsize: %d failed\n",dsize); return -ENOMEM; } if (!(as = alloc_async(ai->framecnt))) { if (data) kfree(data); printk("alloc_async failed\n"); return -ENOMEM; } INIT_LIST_HEAD(&as->asynclist); as->ez = ez; as->userdata = ai->data; as->datalen = dsize; as->context = ai->context; as->urb.dev = ez->usbdev; as->urb.pipe = pipe; as->urb.transfer_flags = USB_ISO_ASAP; as->urb.transfer_buffer = data; as->urb.transfer_buffer_length = dsize; as->urb.context = as; as->urb.complete = (usb_complete_t)async_completed; for (i = totsize = 0; i < as->urb.number_of_packets; i++) { as->urb.iso_frame_desc[i].offset = totsize; if (get_user(j, (int *)(cmd + i * sizeof(struct ezusb_isoframestat)))) { free_async(as); return -EFAULT; } as->urb.iso_frame_desc[i].length = j; totsize += j; } if (dsize > 0 && totsize > 0 && !(ai->ep & 0x80)) { if (copy_from_user(data, ai->data, totsize)) { free_async(as); return -EFAULT; } as->userdata = NULL; /* no need to copy back at completion */ } async_newpending(as); if ((ret = usb_submit_urb(&as->urb))) { printk(KERN_DEBUG "ezusb: iso: usb_submit_urb returned %d\n", ret); async_removepending(as); free_async(as); return -EINVAL; /* return ret; */ } return 0;}static int ezusb_terminateasync(struct ezusb *ez, void *context){ struct async *as; int ret = 0; while ((as = async_getpending(ez, context))) { usb_unlink_urb(&as->urb); ret++; } return ret;}static int ezusb_asynccompl(struct async *as, void *arg){ struct ezusb_asynccompleted *cpl; unsigned int numframes, cplsize, i; if (as->userdata) { if (copy_to_user(as->userdata, as->urb.transfer_buffer, as->datalen)) { free_async(as); return -EFAULT; } } numframes = as->urb.number_of_packets; cplsize = sizeof(struct ezusb_asynccompleted) + numframes * sizeof(struct ezusb_isoframestat); if (!(cpl = kmalloc(cplsize, GFP_KERNEL))) { free_async(as); return -ENOMEM; } cpl->status = as->urb.status; cpl->length = as->urb.actual_length; cpl->context = as->context; for (i = 0; i < numframes; i++) { cpl->isostat[i].length = as->urb.iso_frame_desc[i].length; cpl->isostat[i].status = as->urb.iso_frame_desc[i].status; } free_async(as); if (copy_to_user(arg, cpl, cplsize)) { kfree(cpl); return -EFAULT; } kfree(cpl); return 0;}static int ezusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct ezusb *ez = (struct ezusb *)file->private_data; DECLARE_WAITQUEUE(wait, current); struct usb_proc_ctrltransfer pctrl; struct usb_proc_bulktransfer pbulk; struct usb_proc_old_ctrltransfer opctrl; struct usb_proc_old_bulktransfer opbulk; struct usb_proc_setinterface psetintf; struct ezusb_ctrltransfer ctrl; struct ezusb_bulktransfer bulk; struct ezusb_old_ctrltransfer octrl; struct ezusb_old_bulktransfer obulk; struct ezusb_setinterface setintf; struct ezusb_asyncbulk abulk; struct ezusb_asynciso aiso; struct ezusb_interrupt ezint; struct async *as; void *context; unsigned int ep, cfg; int i, ret = 0; down(&ez->mutex); if (!ez->usbdev) { up(&ez->mutex); return -EIO; } switch (cmd) { case USB_PROC_CONTROL: if (copy_from_user(&pctrl, (void *)arg, sizeof(pctrl))) { ret = -EFAULT; break; } ret = ezusb_control(ez->usbdev, pctrl.requesttype, pctrl.request, pctrl.value, pctrl.index, pctrl.length, (pctrl.timeout * HZ + 500) / 1000, pctrl.data); break; case USB_PROC_BULK: if (copy_from_user(&pbulk, (void *)arg, sizeof(pbulk))) { ret = -EFAULT; break; } ret = ezusb_bulk(ez->usbdev, pbulk.ep, pbulk.len, (pbulk.timeout * HZ + 500) / 1000, pbulk.data); break; case USB_PROC_OLD_CONTROL: if (copy_from_user(&opctrl, (void *)arg, sizeof(opctrl))) { ret = -EFAULT; break; } ret = ezusb_control(ez->usbdev, opctrl.requesttype, opctrl.request, opctrl.value, opctrl.index, opctrl.length, HZ, opctrl.data); break; case USB_PROC_OLD_BULK: if (copy_from_user(&opbulk, (void *)arg, sizeof(opbulk))) { ret = -EFAULT; break; } ret = ezusb_bulk(ez->usbdev, opbulk.ep, opbulk.len, 5*HZ, opbulk.data); break; case USB_PROC_RESETEP: if (get_user(ep, (unsigned int *)arg)) { ret = -EFAULT; break; } ret = ezusb_resetep(ez->usbdev, ep); break; case USB_PROC_SETINTERFACE: if (copy_from_user(&psetintf, (void *)arg, sizeof(psetintf))) { ret = -EFAULT; break; } ret = ezusb_setinterface(ez->usbdev, psetintf.interface, psetintf.altsetting); break; case USB_PROC_SETCONFIGURATION: if (get_user(cfg, (unsigned int *)arg)) { ret = -EFAULT; break; } ret = ezusb_setconfiguration(ez->usbdev, cfg); break; case EZUSB_CONTROL: if (copy_from_user(&ctrl, (void *)arg, sizeof(ctrl))) { ret = -EFAULT; break; } ret = ezusb_control(ez->usbdev, ctrl.requesttype, ctrl.request, ctrl.value, ctrl.index, ctrl.length, (ctrl.timeout * HZ + 500) / 1000, ctrl.data); break; case EZUSB_BULK: if (copy_from_user(&bulk, (void *)arg, sizeof(bulk))) { ret = -EFAULT; break; } ret = ezusb_bulk(ez->usbdev, bulk.ep, bulk.len, (bulk.timeout * HZ + 500) / 1000, bulk.data); break; case EZUSB_OLD_CONTROL: if (copy_from_user(&octrl, (void *)arg, sizeof(octrl))) { ret = -EFAULT; break; } if (octrl.dlen != octrl.length) { ret = -EINVAL; break; } ret = ezusb_control(ez->usbdev, octrl.requesttype, octrl.request, octrl.value, octrl.index, octrl.length, HZ, octrl.data); break; case EZUSB_OLD_BULK: if (copy_from_user(&obulk, (void *)arg, sizeof(obulk))) { ret = -EFAULT; break; } ret = ezusb_bulk(ez->usbdev, obulk.ep, obulk.len, 5*HZ, obulk.data); break; case EZUSB_RESETEP: if (get_user(ep, (unsigned int *)arg)) { ret = -EFAULT; break; } ret = ezusb_resetep(ez->usbdev, ep); break; case EZUSB_SETINTERFACE: if (copy_from_user(&setintf, (void *)arg, sizeof(setintf))) { ret = -EFAULT; break; } ret = ezusb_setinterface(ez->usbdev, setintf.interface, setintf.altsetting); break; case EZUSB_SETCONFIGURATION: if (get_user(cfg, (unsigned int *)arg)) { ret = -EFAULT; break; } ret = ezusb_setconfiguration(ez->usbdev, cfg); break; case EZUSB_ASYNCCOMPLETED: as = NULL; current->state = TASK_INTERRUPTIBLE; add_wait_queue(&ez->wait, &wait); for (;;) { if (!ez->usbdev) break; if ((as = async_getcompleted(ez))) break; if (signal_pending(current)) break; up(&ez->mutex); schedule(); down(&ez->mutex); } remove_wait_queue(&ez->wait, &wait); current->state = TASK_RUNNING; if (as) { ret = ezusb_asynccompl(as, (void *)arg); break; } if (signal_pending(current)) { ret = -EINTR; break; } ret = -EIO; break; case EZUSB_ASYNCCOMPLETEDNB: if ((as = async_getcompleted(ez))) { ret = ezusb_asynccompl(as, (void *)arg); break; } ret = -EAGAIN; break; case EZUSB_REQUESTBULK: if (copy_from_user(&abulk, (void *)arg, sizeof(abulk))) { ret = -EFAULT; break; } ret = ezusb_requestbulk(ez, &abulk); break; case EZUSB_REQUESTISO: if (copy_from_user(&aiso, (void *)arg, sizeof(aiso))) { ret = -EFAULT; break; } ret = ezusb_requestiso(ez, &aiso, ((unsigned char *)arg)+sizeof(aiso)); break; case EZUSB_TERMINATEASYNC: if (get_user(context, (void **)arg)) { ret = -EFAULT; break; } ret = ezusb_terminateasync(ez, context); break; case EZUSB_GETFRAMENUMBER: i = usb_get_current_frame_number(ez->usbdev); ret = put_user(i, (int *)arg); break; case EZUSB_INTERRUPT: printk("INT START\n"); if (copy_from_user(&ezint, (void *)arg, sizeof(ezint))) { ret = -EFAULT; break; } ret=ezusb_interrupt(ez,&ezint); break; default: ret = -ENOIOCTLCMD; break; } up(&ez->mutex); return ret;}static struct file_operations ezusb_fops = { ezusb_llseek, ezusb_read, ezusb_write, NULL, /* readdir */ NULL, /* poll */ ezusb_ioctl, NULL, /* mmap */ ezusb_open, NULL, /* flush */ ezusb_release, NULL, /* fsync */ NULL, /* fasync */ NULL /* lock */};/* --------------------------------------------------------------------- */static void * ezusb_probe(struct usb_device *usbdev, unsigned int ifnum){ struct ezusb *ez = &ezusb[0]; struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint;#undef KERN_DEBUG#define KERN_DEBUG "" printk(KERN_DEBUG "ezusb: probe: vendor id 0x%x, device id 0x%x\n", usbdev->descriptor.idVendor, usbdev->descriptor.idProduct); /* the 1234:5678 is just a self assigned test ID */ if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) #if 1 && (usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x9999) && (usbdev->descriptor.idVendor != 0x1234 || usbdev->descriptor.idProduct != 0x5678) #endif ) return NULL; /* We don't handle multiple configurations */ if (usbdev->descriptor.bNumConfigurations != 1) return NULL;#if 0 /* We don't handle multiple interfaces */ if (usbdev->config[0].bNumInterfaces != 1) return NULL;#endif down(&ez->mutex); if (ez->usbdev) { up(&ez->mutex); printk(KERN_INFO "ezusb: device already used\n"); return NULL; } ez->usbdev = usbdev; if (usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue) < 0) { printk(KERN_ERR "ezusb: set_configuration failed\n"); goto err; } interface = &usbdev->config[0].interface[0].altsetting[1]; if (usb_set_interface(usbdev, 0, 1) < 0) { printk(KERN_ERR "ezusb: set_interface failed\n"); goto err; } up(&ez->mutex); MOD_INC_USE_COUNT; return ez; err: up(&ez->mutex); ez->usbdev = NULL; return NULL;}static void ezusb_disconnect(struct usb_device *usbdev, void *ptr){ struct ezusb *ez = (struct ezusb *)ptr; down(&ez->mutex); destroy_all_async(ez); ez->usbdev = NULL; up(&ez->mutex); wake_up(&ez->wait); MOD_DEC_USE_COUNT;}static struct usb_driver ezusb_driver = { "ezusb", ezusb_probe, ezusb_disconnect, { NULL, NULL }, &ezusb_fops, 192};/* --------------------------------------------------------------------- */int ezusb_init(void){ unsigned u; /* initialize struct */ for (u = 0; u < NREZUSB; u++) { init_MUTEX(&ezusb[u].mutex); ezusb[u].usbdev = NULL; INIT_LIST_HEAD(&ezusb[u].async_pending); INIT_LIST_HEAD(&ezusb[u].async_completed); init_waitqueue_head(&ezusb[u].wait); spin_lock_init(&ezusb[u].lock); } /* register misc device */ usb_register(&ezusb_driver); printk(KERN_INFO "ezusb: Anchorchip firmware download driver registered\n"); return 0;}void ezusb_cleanup(void){ usb_deregister(&ezusb_driver);}/* --------------------------------------------------------------------- */#ifdef MODULEint minor = 192;int init_module(void){ return ezusb_init();}void cleanup_module(void){ ezusb_cleanup();}#endif/* --------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -