接下来从qtd_fill()中返回到qh_urb_transaction()中,再贴一下返回处的代码,如下
1. if (usb_pipecontrol (urb->pipe)) {
2. /* SETUP pid */
3. qtd_fill(ehci, qtd, urb->setup_dma,
4. sizeof (struct usb_ctrlrequest),
5. token | (2 /* "setup" */ << 8), 8);
6. /* ... and always at least one more pid */
7. token ^= QTD_TOGGLE;
8. qtd_prev = qtd;
9. qtd = ehci_qtd_alloc (ehci, flags);
10. if (unlikely (!qtd))
11. goto cleanup;
12. qtd->urb = urb;
13. qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
14. list_add_tail (&qtd->qtd_list, head);
15. /* for zero length DATA stages, STATUS is always IN */
16. if (len == 0)
17. token |= (1 /* "in" */ << 8);
18. }
刚才假设了我们的urb属于控制类传输的参数类型,进入到了if语句中,并主要分析了qtd_fill()函数,知道它把由urb上数据传输相关的内存交换区的地址长度等信息写入到一个qtd中。
上述if语句中第6行到最后,在经过qtd_fill()填充过后的qtd就已经能用于实际的数据传输了,并用qtd_prev指针暂时维持对其的引用,接着在用ehci_qtd_alloc()分配新的qtd,刚才经填充的qtd的hw_next中写入这个新分配的qtd的物理地址,并把新分配的qtd联入head队列中。接着if判断len的值,为零说明当前的urb仅用于Control的命令传输,而没有数据传输,反之urb中还有数据要传输。变量len的值来至urb的transfer_buffer_length,表示了数据传输交换区的长度。
结束了if判断语言的相关内容后,进入到“data transfer stage: buffer setup”,即数据传输阶段,如下代码。
1. /*
2. data transfer stage: buffer setup
3. */
4. i = urb->num_mapped_sgs;
5. if (len > 0 && i > 0) {
6. sg = urb->sg;
7. buf = sg_dma_address(sg);
8. /* urb->transfer_buffer_length may be smaller than the
9. size of the scatterlist (or vice versa)
10. */
11. this_sg_len = min_t(int, sg_dma_len(sg), len);
12. } else {
13. sg = NULL;
14. buf = urb->transfer_dma;
15. this_sg_len = len;
16. }
17. if (is_input)
18. token |= (1 /* "in" */ << 8);
19. /* else it&