📄 fs2410-usbcon.1.1.c
字号:
up(&dev->limit_sem); if (buf) { kfree(buf); } return 0;L_SEND_BULKDATA_ERR: up(&dev->limit_sem); if (buf) { kfree(buf); } return -1; } return 0; break; case IOCTL_GET_ARM_OUTPUT: { if (copy_from_user(&ctlData, (const void *)arg, sizeof(struct IOCTL_DATA_IO))) { retval = -EFAULT; return -1; } if (ctlData.length > 0) { iosize = min(ctlData.length, (size_t)MAX_TRANSFER); /* limit the number of URBs in flight to stop a user from using up all RAM */ if (down_interruptible(&dev->limit_sem)) { retval = -ERESTARTSYS; goto L_GET_OUTPUT_ERR_1; } spin_lock_irq(&dev->err_lock); if ((retval = dev->errors) < 0) { /* any error is reported once */ dev->errors = 0; /* to preserve notifications about reset */ retval = (retval == -EPIPE) ? retval : -EIO; } spin_unlock_irq(&dev->err_lock); if (retval < 0) goto L_GET_OUTPUT_ERR_1; /* allocate memory */ buf = kzalloc(iosize, GFP_KERNEL); if (!buf) { err("Out of memory"); retval = -ENOMEM; goto L_GET_OUTPUT_ERR_1; } /* this lock makes sure we don't submit URBs to gone devices */ mutex_lock(&dev->io_mutex); if (!dev->interface) {/* disconnect() was called */ mutex_unlock(&dev->io_mutex); retval = -ENODEV; goto L_GET_OUTPUT_ERR_1; } /* get the data buffer length */ retval = usb_control_msg( dev->udev, usb_rcvctrlpipe(dev->udev, 0), PIPO0_GET_ARM_OUTPUT_LENGTH, USB_DIR_IN | USB_TYPE_VENDOR, 0, 0, ucLen, 4, 10000); if (retval < 0) { mutex_unlock(&dev->io_mutex); err("%s - failed controling urb to get buffer lenth, error %d", __FUNCTION__, retval); goto L_GET_OUTPUT_ERR_1; } len = ((int)ucLen[0] << 24) + ((int)ucLen[1] << 16) + ((int)ucLen[2] << 8) + (int)ucLen[3]; if (len < iosize) iosize = len; /* get the data buffer */ retval = usb_control_msg( dev->udev, usb_rcvctrlpipe(dev->udev, 0), PIPO0_GET_ARM_OUTPUT, USB_DIR_IN | USB_TYPE_VENDOR, 0, 0, buf, iosize, 10000); mutex_unlock(&dev->io_mutex); if (retval < 0) { err("%s - failed controling urb to get buffer, error %d", __FUNCTION__, retval); goto L_GET_OUTPUT_ERR_1; } if (copy_to_user((void *)ctlData.data, buf, iosize)) { retval = -EFAULT; goto L_GET_OUTPUT_ERR_1; } } ctlData.length = iosize; if (copy_to_user((void *)arg, &ctlData, sizeof(struct IOCTL_DATA_IO))) { retval = -EFAULT; goto L_GET_OUTPUT_ERR_1; } up(&dev->limit_sem); if (buf) { kfree(buf); } return 0;L_GET_OUTPUT_ERR_1: up(&dev->limit_sem); if (buf) { kfree(buf); } return -1; } return 0; break; } err("Unknown command"); return -EFAULT;}int fs2410usbcon_ioctl(struct inode * inode_, struct file * filp, unsigned int cmd, unsigned long arg){ struct usb_fs2410usbcon *dev = (struct usb_fs2410usbcon *)filp->private_data; int retval = 0; char *buf = NULL; size_t iosize = 0; unsigned char ucLen[4]; int len; /* how many bytes can be readed out in the device ? */ struct IOCTL_DATA_IO ctlData; switch (cmd) { case IOCTL_SET_USER_INPUT: { if (copy_from_user(&ctlData, (const void *)arg, sizeof(struct IOCTL_DATA_IO))) { retval = -EFAULT; return -1; } if (ctlData.length > 0) { iosize = min(ctlData.length, (size_t)MAX_TRANSFER); /* limit the number of URBs in flight to stop a user from using up all RAM */ if (down_interruptible(&dev->limit_sem)) { retval = -ERESTARTSYS; goto L_SET_INPUT_ERR_1; } spin_lock_irq(&dev->err_lock); if ((retval = dev->errors) < 0) { /* any error is reported once */ dev->errors = 0; /* to preserve notifications about reset */ retval = (retval == -EPIPE) ? retval : -EIO; } spin_unlock_irq(&dev->err_lock); if (retval < 0) goto L_SET_INPUT_ERR_1; /* allocate memory */ buf = kzalloc(iosize, GFP_KERNEL); if (!buf) { err("Out of memory"); retval = -ENOMEM; goto L_SET_INPUT_ERR_1; } if (copy_from_user(buf, ctlData.data, iosize)) { retval = -EFAULT; goto L_SET_INPUT_ERR_1; } /* this lock makes sure we don't submit URBs to gone devices */ mutex_lock(&dev->io_mutex); if (!dev->interface) {/* disconnect() was called */ mutex_unlock(&dev->io_mutex); retval = -ENODEV; goto L_SET_INPUT_ERR_1; } /* send the data out */ retval = usb_control_msg( dev->udev, usb_sndctrlpipe(dev->udev, 0), PIPO0_SET_USER_INPUT, USB_DIR_OUT | USB_TYPE_VENDOR, 0, 0, buf, iosize, 10000); mutex_unlock(&dev->io_mutex); if (retval < 0) { err("%s - failed controling urb, error %d", __FUNCTION__, retval); goto L_SET_INPUT_ERR_1; } } ctlData.length = iosize; if (copy_to_user((void *)arg, &ctlData, sizeof(struct IOCTL_DATA_IO))) { retval = -EFAULT; goto L_SET_INPUT_ERR_1; } up(&dev->limit_sem); if (buf) { kfree(buf); } return 0;L_SET_INPUT_ERR_1: up(&dev->limit_sem); if (buf) { kfree(buf); } return -1; } return 0; break; case IOCTL_GET_ARM_OUTPUT: { if (copy_from_user(&ctlData, (const void *)arg, sizeof(struct IOCTL_DATA_IO))) { retval = -EFAULT; return -1; } if (ctlData.length > 0) { iosize = min(ctlData.length, (size_t)MAX_TRANSFER); /* limit the number of URBs in flight to stop a user from using up all RAM */ if (down_interruptible(&dev->limit_sem)) { retval = -ERESTARTSYS; goto L_GET_OUTPUT_ERR_1; } spin_lock_irq(&dev->err_lock); if ((retval = dev->errors) < 0) { /* any error is reported once */ dev->errors = 0; /* to preserve notifications about reset */ retval = (retval == -EPIPE) ? retval : -EIO; } spin_unlock_irq(&dev->err_lock); if (retval < 0) goto L_GET_OUTPUT_ERR_1; /* allocate memory */ buf = kzalloc(iosize, GFP_KERNEL); if (!buf) { err("Out of memory"); retval = -ENOMEM; goto L_GET_OUTPUT_ERR_1; } /* this lock makes sure we don't submit URBs to gone devices */ mutex_lock(&dev->io_mutex); if (!dev->interface) {/* disconnect() was called */ mutex_unlock(&dev->io_mutex); retval = -ENODEV; goto L_GET_OUTPUT_ERR_1; } /* get the data buffer length */ retval = usb_control_msg( dev->udev, usb_rcvctrlpipe(dev->udev, 0), PIPO0_GET_ARM_OUTPUT_LENGTH, USB_DIR_IN | USB_TYPE_VENDOR, 0, 0, ucLen, 4, 10000); if (retval < 0) { mutex_unlock(&dev->io_mutex); err("%s - failed controling urb to get buffer lenth, error %d", __FUNCTION__, retval); goto L_GET_OUTPUT_ERR_1; } len = ((int)ucLen[0] << 24) + ((int)ucLen[1] << 16) + ((int)ucLen[2] << 8) + (int)ucLen[3]; if (len < iosize) iosize = len; /* get the data buffer */ retval = usb_control_msg( dev->udev, usb_rcvctrlpipe(dev->udev, 0), PIPO0_GET_ARM_OUTPUT, USB_DIR_IN | USB_TYPE_VENDOR, 0, 0, buf, iosize, 10000); mutex_unlock(&dev->io_mutex); if (retval < 0) { err("%s - failed controling urb to get buffer, error %d", __FUNCTION__, retval); goto L_GET_OUTPUT_ERR_1; } if (copy_to_user((void *)ctlData.data, buf, iosize)) { retval = -EFAULT; goto L_GET_OUTPUT_ERR_1; } } ctlData.length = iosize; if (copy_to_user((void *)arg, &ctlData, sizeof(struct IOCTL_DATA_IO))) { retval = -EFAULT; goto L_GET_OUTPUT_ERR_1; } up(&dev->limit_sem); if (buf) { kfree(buf); } return 0;L_GET_OUTPUT_ERR_1: up(&dev->limit_sem); if (buf) { kfree(buf); } return -1; } return 0; break; } err("Unknown command"); return -EFAULT;}static const struct file_operations fs2410usbcon_fops = { .owner = THIS_MODULE, .read = fs2410usbcon_read2, .write = fs2410usbcon_write2, .ioctl = fs2410usbcon_ioctl, .open = fs2410usbcon_open, .release = fs2410usbcon_release, .flush = fs2410usbcon_flush,};/* * usb class driver info in order to get a minor number from the usb core, * and to have the device registered with the driver core */static struct usb_class_driver fs2410usbcon_class = { .name = "fs2410usbcon%d", .fops = &fs2410usbcon_fops, .minor_base = USB_FS2410USBCON_MINOR_BASE,};static int fs2410usbcon_probe(struct usb_interface *interface, const struct usb_device_id *id){ struct usb_fs2410usbcon *dev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; size_t buffer_size; int i; int retval = -ENOMEM; /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { err("Out of memory"); goto error; } kref_init(&dev->kref); sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); mutex_init(&dev->io_mutex); spin_lock_init(&dev->err_lock); init_usb_anchor(&dev->submitted); dev->udev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; /* set up the endpoint information */ /* use only the first bulk-in and bulk-out endpoints */ iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); dev->bulk_in_size = buffer_size; dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!dev->bulk_in_buffer) { err("Could not allocate bulk_in_buffer"); goto error; } } if (!dev->bulk_out_endpointAddr && usb_endpoint_is_bulk_out(endpoint)) { /* we found a bulk out endpoint */ dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; } } if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { err("Could not find both bulk-in and bulk-out endpoints"); goto error; } /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); /* we can register the device now, as it is ready */ retval = usb_register_dev(interface, &fs2410usbcon_class); if (retval) { /* something prevented us from registering this driver */ err("Not able to get a minor for this device."); usb_set_intfdata(interface, NULL); goto error; } /* let the user know what node this device is now attached to */ info("USB fs2410usbcon device now attached to USBFS2410usbcon-%d", interface->minor); return 0;error: if (dev) /* this frees allocated memory */ kref_put(&dev->kref, fs2410usbcon_delete); return retval;}static void fs2410usbcon_disconnnect(struct usb_interface *interface){ struct usb_fs2410usbcon *dev; int minor = interface->minor; dev = usb_get_intfdata(interface); usb_set_intfdata(interface, NULL); /* give back our minor */ usb_deregister_dev(interface, &fs2410usbcon_class); /* prevent more I/O from starting */ mutex_lock(&dev->io_mutex); dev->interface = NULL; mutex_unlock(&dev->io_mutex); usb_kill_anchored_urbs(&dev->submitted); /* decrement our usage count */ kref_put(&dev->kref, fs2410usbcon_delete); info("USB fs2410usbcon #%d now disconnected", minor);}static void fs2410usbcon_draw_down(struct usb_fs2410usbcon *dev){ int time; time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000); if (!time) usb_kill_anchored_urbs(&dev->submitted);}static int fs2410usbcon_suspend(struct usb_interface *intf, pm_message_t message){ struct usb_fs2410usbcon *dev = usb_get_intfdata(intf); if (!dev) return 0; fs2410usbcon_draw_down(dev); return 0;}static int fs2410usbcon_resume (struct usb_interface *intf){ return 0;}static int fs2410usbcon_pre_reset(struct usb_interface *intf){ struct usb_fs2410usbcon *dev = usb_get_intfdata(intf); mutex_lock(&dev->io_mutex); fs2410usbcon_draw_down(dev); return 0;}static int fs2410usbcon_post_reset(struct usb_interface *intf){ struct usb_fs2410usbcon *dev = usb_get_intfdata(intf); /* we are sure no URBs are active - no locking needed */ dev->errors = -EPIPE; mutex_unlock(&dev->io_mutex); return 0;}static struct usb_driver fs2410usbcon_driver = { .name = "fs2410usbcon", .probe = fs2410usbcon_probe, .disconnect = fs2410usbcon_disconnnect, .suspend = fs2410usbcon_suspend, .resume = fs2410usbcon_resume, .pre_reset = fs2410usbcon_pre_reset, .post_reset = fs2410usbcon_post_reset, .id_table = fs2410usbcon_table, .supports_autosuspend = 1,};static int __init usb_fs2410usbcon_init(void){ int result; /* register this driver with the USB subsystem */ result = usb_register(&fs2410usbcon_driver); if (result) err("usb_register failed. Error number %d", result); return result;}static void __exit usb_fs2410usbcon_exit(void){ /* deregister this driver with the USB subsystem */ usb_deregister(&fs2410usbcon_driver);}module_init(usb_fs2410usbcon_init);module_exit(usb_fs2410usbcon_exit);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -