匹配成功后,按照套路就该请probe上场了
490 static int skel_probe(struct usb_interface *interface, 491 const struct usb_device_id *id) 492 { 493 struct usb_skel *dev; 494 struct usb_host_interface *iface_desc; 495 struct usb_endpoint_descriptor *endpoint; 496 size_t buffer_size; 497 int i; 498 int retval = -ENOMEM; 499 500 /* allocate memory for our device state and initialize it */ 501 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 506 kref_init(&dev->kref); 507 sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); 508 mutex_init(&dev->io_mutex); 509 spin_lock_init(&dev->err_lock); 510 init_usb_anchor(&dev->submitted); 511 init_waitqueue_head(&dev->bulk_in_wait); 512 513 dev->udev = usb_get_dev(interface_to_usbdev(interface)); 514 dev->interface = interface; 515 516 /* set up the endpoint information */ 517 /* use only the first bulk-in and bulk-out endpoints */ 518 iface_desc = interface->cur_altsetting; 519 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 520 endpoint = &iface_desc->endpoint[i].desc; 521 522 if (!dev->bulk_in_endpointAddr && 523 usb_endpoint_is_bulk_in(endpoint)) { 524 /* we found a bulk in endpoint */ 525 buffer_size = usb_endpoint_maxp(endpoint); 526 dev->bulk_in_size = buffer_size; 527 dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; 528 dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); 534 dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL); 540 } 542 if (!dev->bulk_out_endpointAddr && 543 usb_endpoint_is_bulk_out(endpoint)) { 544 /* we found a bulk out endpoint */ 545 dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; 546 } 547 } 553 554 /* save our data pointer in this interface device */ 555 usb_set_intfdata(interface, dev); 556 557 /* we can register the device now, as it is ready */ 558 retval = usb_register_dev(interface, &skel_class); 566 567 /* let the user know what node this device is now attached to */ 568 dev_info(&interface->dev, 569 "USB Skeleton device now attached to USBSkel-%d", 570 interface->minor); 571 return 0; 578 } 579skel_probe
--501-->为资源对象申请空间, 注意这里的写法: dev = kzalloc(sizeof(*dev), GFP_KERNEL);
--506-->初始化usb_skel->kref
--507-->初始化usb_skel->limit_sem
--508-->初始化usb_skel->io_mutex);
--509-->初始化usb_skel->err_lock);
--510-->初始化usb_skel->submitted);
--511-->初始化usb_skel->bulk_in_wait
--513-->初始化usb_skel->udev,将匹配到的usb_device地址存储下来
--514-519-->初始化usb_skel对象其他域.
--555-->将我们的资源对象藏到interface->dev->p->driver_data中
--558-->注册一个usb_device对象到内核、申请一个次设备号并创建设备文件, ==>intf->usb_dev = device_create(usb_class->class, &intf->dev,MKDEV(USB_MAJOR, minor), class_driver,"%s", temp);
通过上面的分析, 我们发现了一个skeleton和usbmouse不一样的地方:skeleton构造了usb_class_driver对象并使用usb_register_dev注册一个usb设备, 而usbmouse作为input子系统, 仅需要input_register(input_dev)即可, 不用usb设备的注册问题, 产生这个差别的原因是skeleton是针对bulk urb设备的, 而usbmouse是针对interrupt urb设备的。对于bulk设备,我们会对设备进行读写操作,而不仅仅是读操作,所以在bulk urb设备驱动中要实现相应的操作方法集并绑定到设备文件一起注册到内核,这个工作就是由usb_register_dev来完成。为了使用这个函数,我们需要构造一个usb_class_driver对象,其中最重要的就是本节要讨论的skel_fops了。这个域也是struct file_operations类型的,所有的读写方法的实现都要注册到这个域中。
既然提到fops,我们主要关心的就三个方法的实现:open, read和write,考虑到read和write在操作逻辑类似,所以本文只讨论open和read