/* * This is my USB driver * Copyright (C) 2004 Rick Huang * Revision History: * First release: Feb 10, 2004 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __KERNEL__ # define __KERNEL__ #endif #ifndef MODULE # define MODULE #endif #include #include #include #include #include #include #include struct my_device{ unsigned char data[64]; struct urb urb; int max_packet_size; char output[80]; }; struct my_proc_data{ struct my_device *mydev; struct usb_device *udev; }; static struct proc_dir_entry *myusb_file; static struct my_proc_data Lprocdata; static void my_device_callback(struct urb *urb) { struct my_device *mydev = urb->context; /*char *msg = mydev->output;*/ int i; if(urb->status != USB_ST_NOERROR)return; /*use sprintf to print some debug message if you wish. */ /*printk(KERN_INFO "%s\n", mydev->output);*/ } static void my_device_disconnect(struct usb_device *udev, void *clientdata) { struct my_device *mydev = clientdata; usb_unlink_urb(&mydev->urb); kfree(mydev); printk(KERN_INFO "myusb: USB device disconnected\n"); Lprocdata.mydev = NULL; return; } static void *my_device_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) { struct usb_interface *iface; struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct my_device *mydev; if(Lprocdata.mydev != NULL) { printk(KERN_INFO "myusb: The driver can not support more than one devices\n"); return NULL; } printk(KERN_INFO "myusb: probe called for %s device\n", (char *)id->driver_info); iface = &udev->actconfig->interface[ifnum]; interface = &iface->altsetting[iface->act_altsetting]; if(interface->bNumEndpoints != 2) return NULL; endpoint = interface->endpoint; if(!(endpoint->bEndpointAddress & 0x01)) return NULL; /* OUT EP */ if((endpoint->bmAttributes &2 ) != 2)return NULL; /* BULK TRANSFER */ mydev = kmalloc(sizeof(struct my_device), GFP_KERNEL); if(!mydev)return NULL; memset (mydev, 0, sizeof(*mydev)); { int pipe = usb_sndbulkpipe(udev, 1); int length; mydev->max_packet_size = 64; strcpy(mydev->data, "Hello World"); length = strlen(mydev->data); FILL_BULK_URB(&mydev->urb, udev, pipe, mydev->data, length, my_device_callback, mydev); } if(usb_submit_urb(&mydev->urb)){ kfree(mydev); return NULL; } printk(KERN_INFO "myusb: probe successful.\n"); Lprocdata.mydev = mydev; Lprocdata.udev = udev; return mydev; } static int proc_write_myusb(struct file *file, const char *buffer, unsigned long count, void *data) { int len; struct my_proc_data *procdata=(struct my_proc_data *)data; struct my_device *mydev=procdata->mydev; if(procdata->mydev == NULL){return 1;} { int pipe = usb_sndbulkpipe(procdata->udev, 1); int maxp; if(count > 64) maxp = 64; else maxp = count; len = maxp; strncpy(mydev->data, buffer, len); FILL_BULK_URB(&mydev->urb, procdata->udev, pipe, mydev->data, maxp, my_device_callback, mydev); } if(usb_submit_urb(&mydev->urb)){ printk(KERN_INFO "myusb: Error sending USB packet.\n"); } return 1; } static int proc_read_myusb(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; struct my_proc_data *procdata=(struct my_proc_data *)data; struct my_device *mydev=procdata->mydev; if(procdata->mydev == NULL){len = sprintf(page, "Not Attached!\n");return len;} /* { int pipe = usb_rcvbulkpipe(procdata->udev, 1); int max; FILL_BULK_URB(&mydev->urb, procdata->udev, pipe, mydev->data, max, my_device_callback, mydev); } if(usb_submit_urb(&mydev->urb)){ len = sprintf(page, "Error sending USB packet!\n"); return len; } */ { unsigned int partial; int result = usb_bulk_msg(procdata->udev, usb_rcvbulkpipe(procdata->udev, 1), mydev->data, 64, &partial, (int) (HZ * 8)); if(result != 0) { len = sprintf(page, "Error reading data (%d)\n", result); return len; } mydev->data[partial] = 0; len = sprintf(page, "Data read %d bytes: %s \n", partial, mydev->data); } return len; } static struct usb_device_id my_device_id_table[] = { { USB_INTERFACE_INFO(255, 255, 255), driver_info: (unsigned long)"my_usb" }, { 0, } }; static struct usb_driver mydev_usb_driver = { name: "my_usb", probe: my_device_probe, disconnect: my_device_disconnect, id_table: my_device_id_table, }; int my_device_init(void) { myusb_file = create_proc_entry("myusb", 0666, NULL); if(myusb_file == NULL){return -ENOMEM;} Lprocdata.mydev = NULL; myusb_file->data = &Lprocdata; myusb_file->read_proc = &proc_read_myusb; myusb_file->write_proc = &proc_write_myusb; myusb_file->owner = THIS_MODULE; return usb_register(&mydev_usb_driver); } void my_device_exit(void) { usb_deregister(&mydev_usb_driver); remove_proc_entry("myusb", NULL); printk(KERN_INFO "myusb proc file removed.\n"); } module_init(my_device_init); module_exit(my_device_exit); MODULE_AUTHOR("R HUANG"); MODULE_DESCRIPTION("Myusb device driver for testing my own usb device"); MODULE_LICENSE("GPL");