uvc_driver.txt(temp)

来源:互联网 发布:数据挖掘会议 2017 编辑:程序博客网 时间:2024/05/29 02:26

 

提交urb的实现
*******************************************************************************************
rh_queue_status
 // 将urb插入endpoint的链表中
 retval = usb_hcd_link_urb_to_ep(hcd, urb);


.
/* Host side RX (IN) using Mentor DMA works as follows:
 submit_urb ->
  - if queue was empty, ProgramEndpoint
  - first IN token is sent out (by setting ReqPkt)
 LinuxIsr -> RxReady()
 /\ => first packet is received
 | - Set in mode 0 (DmaEnab, ~ReqPkt)
 |  -> DMA Isr (transfer complete) -> RxReady()
 |      - Ack receive (~RxPktRdy), turn off DMA (~DmaEnab)
 |      - if urb not complete, send next IN token (ReqPkt)
 |      |  else complete urb.
 |      |
 ---------------------------

musb_host_rx // 在drivers/usb/usb20/musb_host.c中

 

. 发生EXDEV的原因
musb_host_rx
    if (rx_count > d->length) {
     // (1)增加urb的error_count成员的计数
     if (d_status == 0) {
      d_status = -EOVERFLOW;
      urb->error_count++;
     }
     DBG(2, "** OVERFLOW %d into %d\n",\
         rx_count, d->length);
  // (2)将urb的state成员设置为EXDEV
  musb_advance_schedule(musb, urb, hw_ep, USB_DIR_IN);
   case USB_ENDPOINT_XFER_ISOC:
    if (status == 0 && urb->error_count)
     status = -EXDEV;
    break;
   }


. 在musb_host_rx函数中积累urb的number_of_packets成员数量的packet之后调用musb_advance_schedule将这个urb交给urb的complete函数处理:
musb_host_rx
  if (usb_pipeisoc(pipe)) {
   struct usb_iso_packet_descriptor *d;

   d = urb->iso_frame_desc + qh->iso_idx;
   d->actual_length = xfer_len;

   /* even if there was an error, we did the dma
    * for iso_frame_desc->length
    */
   if (d->status != -EILSEQ && d->status != -EOVERFLOW)
    d->status = 0;

   if (++qh->iso_idx >= urb->number_of_packets)
    done = true;
   else
    done = false;

finish:
 urb->actual_length += xfer_len;
 qh->offset += xfer_len;
 if (done) { // 如果条件为真,让urb的complete函数处理这个urb。
  if (use_sg)
   use_sg = false;

  if (urb->status == -EINPROGRESS)
   urb->status = status;
  musb_advance_schedule(musb, urb, hw_ep, USB_DIR_IN);

 

. 在musb_host_rx函数中,调用musb_host_packet_rx,在这个函数中,调用musb_read_fifo(hw_ep, length, buf)从fifo中读取一个urb中一个数据包的数据。
读取的目标地址是urb中数据包指向的地址。读取的大小是一个数据包的大小。只有当urb中的所有数据包都读到数据之后,这个函数才返回done(1)。

.    DBG(4, "RX%d count %d, buffer 0x%x len %d/%d\n",
     epnum, rx_count,
     (unsigned int)urb->transfer_dma
      + urb->actual_length,
     qh->offset,
     urb->transfer_buffer_length);

<5>[  115.854718]<2>-(0)[0:swapper/0][zhongcai]RX2 count 12, buffer 0x777a000c len 12/98304
<5>[  115.855217]<2>-(0)[0:swapper/0][zhongcai]RX2 count 12, buffer 0x777a0018 len 24/98304
<5>[  115.855338]<2>-(0)[0:swapper/0][zhongcai]RX2 count 12, buffer 0x777a0024 len 36/98304
<5>[  115.855463]<2>-(0)[0:swapper/0][zhongcai]RX2 count 12, buffer 0x777a0030 len 48/98304

rx_count: 本次接收到的字节数,比如上面的例子中,4次都是每次接收12字节;
urb->transfer_dma + urb->actual_length:urb当前存放数据的dma地址(因为之前已经存储了数据,urb->actual_length是urb目前接收到的数据的长度);
qh->offset:urb当前数据的offset(因为之前已经接收了数据);
urb->transfer_buffer_length:urb缓冲区的大小。


. urb中actual size成员的更新(在musb_host_rx函数中)
(1)在musb_host_rx函数中,如果urb的成员status是EINPROGRESS,则本次urb的actual_length成员的大小不会更新。这种情况dma指针不是null。
musb_host_rx
 } else if (urb->status == -EINPROGRESS) {
  if (dma) { 
   DBG(4, "RX%d count %d, buffer 0x%x len %d/%d\n",
(2)但是如果在musb_host_rx函数中,执行的是如下的分支,这个urb的actual size成员本次会更新,会增加dma结构中actual_len成员值的大小:
musb_host_rx
 if (dma && (rx_csr & MUSB_RXCSR_DMAENAB)) {
  xfer_len = dma->actual_len;

. hw_ep->regs的设定
(1)musb->mregs的设定
musb_probe
 musb_init_controller(dev, irq, base, pbase)
  allocate_instance
   musb->mregs = mbase;
(2)基于musb->mregs设定hw_ep->regs
musb_core_init
 void __iomem *mbase = musb->mregs;
 
 for (i = 0; i < musb->nr_endpoints; i++) {
  struct musb_hw_ep *hw_ep = musb->endpoints + i;

  hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;
  hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase;


.
void musb_start(struct musb *musb)
 musb_platform_enable(musb);
  musb_gadget_enable

. musb中的musb_platform_ops类型成员ops指向如下的结构:
static const struct musb_platform_ops mt_usb_ops = {
 .init  = mt_usb_init,
 .exit  = mt_usb_exit,
 /*.set_mode = mt_usb_set_mode,*/
 .try_idle = mt_usb_try_idle,
 .enable  = mt_usb_enable,
 .disable = mt_usb_disable,
 .set_vbus = mt_usb_set_vbus,
 .vbus_status = mt_usb_get_vbus_status

. add higg bandwidth rx iso support
http://markmail.org/message/4euuqryd23heygh5#query:+page:1+mid:4gk52yqkcphyiock+state:results


 

0 0