#include #include #include #define MIN(a,b) (((a) <= (b)) ? (a) : (b)) #define BULK_EP_OUT 0x01 #define BULK_EP_IN 0x82 #define MAX_PKT_SIZE 512 static struct usb_device *device; static struct usb_class_driver class; static unsigned char bulk_buf[MAX_PKT_SIZE]; static int thumb_open(struct inode *i, struct file *f) { return 0; } static int thumb_close(struct inode *i, struct file *f) { return 0; } static ssize_t thumb_read(struct file *f, char __user *buf, size_t cnt, loff_t *off) { int retval; int read_cnt; /* Read the data from the bulk endpoint */ retval = usb_bulk_msg(device, usb_rcvbulkpipe(device, BULK_EP_IN), bulk_buf, MAX_PKT_SIZE, &read_cnt, 5000); if (retval) { printk(KERN_ERR "Bulk message returned %d\n", retval); return retval; } if (copy_to_user(buf, bulk_buf, MIN(cnt, read_cnt))) { return -EFAULT; } return MIN(cnt, read_cnt); } static ssize_t thumb_write(struct file *f, const char __user *buf, size_t cnt, loff_t *off) { int retval; int wrote_cnt = MIN(cnt, MAX_PKT_SIZE); if (copy_from_user(bulk_buf, buf, MIN(cnt, MAX_PKT_SIZE))) { return -EFAULT; } /* Write the data into the bulk endpoint */ retval = usb_bulk_msg(device, usb_sndbulkpipe(device, BULK_EP_OUT), bulk_buf, MIN(cnt, MAX_PKT_SIZE), &wrote_cnt, 5000); if (retval) { printk(KERN_ERR "Bulk message returned %d\n", retval); return retval; } return wrote_cnt; } static struct file_operations fops = { .open = thumb_open, .release = thumb_close, .read = thumb_read, .write = thumb_write, }; static int thumb_probe(struct usb_interface *interface, const struct usb_device_id *id) { int retval; device = interface_to_usbdev(interface); class.name = "usb/thumb%d"; class.fops = &fops; if ((retval = usb_register_dev(interface, &class)) < 0) { /* Something prevented us from registering this driver */ printk(KERN_ERR "Not able to get a minor for this device %d\n", retval); } else { printk(KERN_INFO "Minor obtained: %d\n", interface->minor); } return retval; } static void thumb_disconnect(struct usb_interface *interface) { usb_deregister_dev(interface, &class); } static struct usb_device_id thumb_table[] = { { USB_DEVICE(0x0781, 0x5408) }, {} /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, thumb_table); static struct usb_driver thumb_driver = { .name = "thumb_driver", .id_table = thumb_table, .probe = thumb_probe, .disconnect = thumb_disconnect, }; static int __init thumb_init(void) { return usb_register(&thumb_driver); } static void __exit thumb_exit(void) { usb_deregister(&thumb_driver); } module_init(thumb_init); module_exit(thumb_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michael Mitchell"); MODULE_DESCRIPTION("USB Thumb Drive Demo");