USB Core 八

来源:互联网 发布:js单例模式 编辑:程序博客网 时间:2024/06/01 11:27
//将提交过来的urb 指派给合适的主机控制器驱动程序 int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) { int status; struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);/* static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) { return &hcd->self; } static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus) { return container_of(bus, struct usb_hcd, self); }*/ struct usb_host_endpoint *ep; unsigned long flags; if (!hcd) return -ENODEV;/*usbmon_urb_submit 就是与前面Greg 孕育出来的usb Monitor 有关的,如果你编译内核的时候没有配置上CONFIG_USB_MON,它就啥也不是,一个空函数,一具空壳。*/ usbmon_urb_submit(&hcd->self, urb); /* * Atomically queue the urb, first to our records, then to the HCD. * Access to urb->status is controlled by urb->lock ... changes on * i/o completion (normal or fault) or unlinking. */ // FIXME: verify that quiescing hc works right (RH cleans up) spin_lock_irqsave (&hcd_data_lock, flags); ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out) [usb_pipeendpoint(urb->pipe)]; if (unlikely (!ep)) status = -ENOENT; else if (unlikely (urb->reject))//目的端点为空的可能性太小了,所以加上了unlikely status = -EPERM; else switch (hcd->state) { case HC_STATE_RUNNING: case HC_STATE_RESUMING: doit: list_add_tail (&urb->urb_list, &ep->urb_list); status = 0; break; case HC_STATE_SUSPENDED: /* HC upstream links (register access, wakeup signaling) can work * even when the downstream links (and DMA etc) are quiesced;let * usbcore talk to the root hub. */ if (hcd->self.controller->power.power_state.event ==PM_EVENT_ON&& urb->dev->parent == NULL) goto doit; /* FALL THROUGH */ default: status = -ESHUTDOWN; break; } spin_unlock_irqrestore (&hcd_data_lock, flags); if (status) { INIT_LIST_HEAD (&urb->urb_list); usbmon_urb_submit_error(&hcd->self, urb, status); return status; } /* increment urb's reference count as part of giving it to the HCD * (which now controls it). HCD guarantees that it either returns * an error or calls giveback(), but not both. */ urb = usb_get_urb (urb);//可以放心的增加urb 的引用计数了 atomic_inc (&urb->use_count);//将urb 的use_count 也增加1,表示urb 已经被HCD 接受了,正在被处理着。 if (urb->dev == hcd->self.root_hub) { /* NOTE: requirement on hub callers (usbfs and the hub * driver, for now) that URBs' urb->transfer_buffer be * valid and usb_buffer_{sync,unmap}() not be needed, since * they could clobber root hub response data. */ status = rh_urb_enqueue (hcd, urb); goto done; } /* lower level hcd code should use *_dma exclusively, * unless it uses pio or talks to another transport. *//*如果这个主机控制器支持DMA,可你却没有告诉它URB_NO_SETUP_DMA_MAP或URB_NO_TRANSFER_DMA_MAP 这两个标志,它就会认为你在urb 里没有提供DMA的缓冲区,就会调用dma_map_single将setup_packet 或transfer_buffer映射为DMA缓冲区。*/ if (hcd->self.uses_dma) { if (usb_pipecontrol (urb->pipe)&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) urb->setup_dma = dma_map_single (hcd->self.controller,urb->setup_packet,sizeof (struct usb_ctrlrequest),DMA_TO_DEVICE); if (urb->transfer_buffer_length != 0&& !(urb->transfer_flags &URB_NO_TRANSFER_DMA_MAP)) urb->transfer_dma = dma_map_single (hcd->self.controller,urb->transfer_buffer,urb->transfer_buffer_length,usb_pipein (urb->pipe)? DMA_FROM_DEVICE: DMA_TO_DEVICE); } status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags); //终于可以将urb 扔给具体的主机控制器驱动程序了 done: if (unlikely (status)) { urb_unlink (urb); atomic_dec (&urb->use_count); if (urb->reject) wake_up (&usb_kill_urb_queue); usbmon_urb_submit_error(&hcd->self, urb, status); usb_put_urb (urb); }    return status; }


 

原创粉丝点击