staticintskel_probe(struct usb_interface *interface,conststruct usb_device_id *id){struct usb_skel *dev;struct usb_host_interface *iface_desc;struct usb_endpoint_descriptor *endpoint;
size_t buffer_size;int i;int retval =-ENOMEM;/*1. 为设备分配内存并初始化设备*/
dev =kzalloc(sizeof(*dev), GFP_KERNEL);...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);init_waitqueue_head(&dev->bulk_in_wait);
dev->udev =usb_get_dev(interface_to_usbdev(interface));
dev->interface = interface;/*2. set up端点信息*//*仅使用第一个bulk-in和bulk-out端点*/
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)){
buffer_size =usb_endpoint_maxp(endpoint);
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)...
dev->bulk_in_urb =usb_alloc_urb(0, GFP_KERNEL);if(!dev->bulk_in_urb)...}if(!dev->bulk_out_endpointAddr &&usb_endpoint_is_bulk_out(endpoint)){
dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;}}if(!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)){dev_err(&interface->dev,"Could not find both bulk-in and bulk-out endpoints\n");...}/*3. 保存数据指针到该接口设备*/usb_set_intfdata(interface, dev);/*4. 注册该设备*/
retval =usb_register_dev(interface,&skel_class);if(retval){dev_err(&interface->dev,"Not able to get a minor for this device.\n");usb_set_intfdata(interface,NULL);...}/*4. 打印设备节点*/dev_info(&interface->dev,"USB Skeleton device now attached to USBSkel-%d",
interface->minor);return0;}staticvoidskel_disconnect(struct usb_interface *interface){struct usb_skel *dev;int minor = interface->minor;
dev =usb_get_intfdata(interface);usb_set_intfdata(interface,NULL);/*1. 注销该usb设备,释放次设备号*/usb_deregister_dev(interface,&skel_class);/*2. 阻止更多的I/O启动*/mutex_lock(&dev->io_mutex);
dev->interface =NULL;mutex_unlock(&dev->io_mutex);usb_kill_anchored_urbs(&dev->submitted);/*3. 减少引用计数*/kref_put(&dev->kref, skel_delete);dev_info(&interface->dev,"USB Skeleton #%d now disconnected", minor);}
3)定义特定的设备数据结构;
struct usb_skel {struct usb_device *udev;/* the usb device for this device */struct usb_interface *interface;/* the interface for this device */struct semaphore limit_sem;/* limiting the number of writes in progress */struct usb_anchor submitted;/* in case we need to retract our submissions */struct urb *bulk_in_urb;/* the urb to read data with */unsignedchar*bulk_in_buffer;/* the buffer to receive data */
size_t bulk_in_size;/* the size of the receive buffer */
size_t bulk_in_filled;/* number of bytes in the buffer */
size_t bulk_in_copied;/* already copied to user space */
__u8 bulk_in_endpointAddr;/* the address of the bulk in endpoint */
__u8 bulk_out_endpointAddr;/* the address of the bulk out endpoint */int errors;/* the last request tanked */
bool ongoing_read;/* a read is going on */
spinlock_t err_lock;/* lock for errors */struct kref kref;struct mutex io_mutex;/* synchronize I/O with disconnect */
wait_queue_head_t bulk_in_wait;/* to wait for an ongoing read */};