Chinaunix首页 | 论坛 | 博客
  • 博客访问: 216815
  • 博文数量: 32
  • 博客积分: 410
  • 博客等级: 一等列兵
  • 技术积分: 396
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-03 16:58
文章分类

全部博文(32)

文章存档

2013年(17)

2012年(15)

我的朋友

分类: LINUX

2013-04-21 21:34:10


老早听人讲,usb hub有一个而且只有一个INT_POINT;
所以按照操作流程,你想访问它,必须这样来:
 
usb_submit_urb()-->usb_hcd_submit_urb()-->rh_queue_status()-->rh_timer_func()-->usb_hcd_poll_rh_status()
1:在usb_submit_urb()中有:
if (urb->interval > (1024 * 8))
    urb->interval = 1024 * 8;
2:在usb_hcd_submit_urb()中有:
if (is_root_hub(urb->dev))
   status = rh_urb_enqueue(hcd, urb);
3:在rh_urb_enqueue中有
    if (usb_endpoint_xfer_int(&urb->ep->desc))
        return rh_queue_status (hcd, urb);
4:在rh_queue_status()

/*-------------------------------------------------------------------------*/

点击(此处)折叠或打开

  1. static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
  2. {
  3.     int retval;
  4.     unsigned long flags;
  5.     unsigned len = 1 + (urb->dev->maxchild / 8);

  6.     spin_lock_irqsave (&hcd_root_hub_lock, flags);
  7.     if (hcd->status_urb || urb->transfer_buffer_length < len) {
  8.         dev_dbg (hcd->self.controller, "not queuing rh status urb\n");
  9.         retval = -EINVAL;
  10.         goto done;
  11.     }

  12.     retval = usb_hcd_link_urb_to_ep(hcd, urb);
  13.     if (retval)
  14.         goto done;

  15.     hcd->status_urb = urb;
  16.     urb->hcpriv = hcd; /* indicate it


靠,搞不明白了:中断传输呢??

百度,再百度,在网上找到这么一句话,
Root Hub interrupt transfers are polled using a timer if the driver requests it;
也就是讲,roothub的中断传输,其实用个定时器,去访问HC的register;快晕菜了;

点击(此处)折叠或打开

  1. /*-------------------------------------------------------------------------*/

  2. /*
  3.  * Root Hub interrupt transfers are polled using a timer if the
  4.  * driver requests it; otherwise the driver is responsible for
  5.  * calling usb_hcd_poll_rh_status() when an event occurs.
  6.  *
  7.  * Completions are called in_interrupt(), but they may or may not
  8.  * be in_irq().
  9.  */
  10. void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
  11. {
  12.     struct urb *urb;
  13.     int length;
  14.     unsigned long flags;
  15.     char buffer[6]; /* Any root hubs with > 31 ports? */

  16.     if (unlikely(!hcd->rh_registered))
  17.         return;
  18.     if (!hcd->uses_new_polling && !hcd->status_urb)
  19.         return;

  20.     length = hcd->driver->hub_status_data(hcd, buffer);
  21.     if (length > 0) {

  22.         /* try to complete the status urb */
  23.         spin_lock_irqsave(&hcd_root_hub_lock, flags);
  24.         urb = hcd->status_urb;
  25.         if (urb) {
  26.             hcd->poll_pending = 0;
  27.             hcd->status_urb = NULL;
  28.             urb->actual_length = length;
  29.             memcpy(urb->transfer_buffer, buffer, length);

  30.             usb_hcd_unlink_urb_from_ep(hcd, urb);
  31.             spin_unlock(&hcd_root_hub_lock);
  32.             usb_hcd_giveback_urb(hcd, urb, 0);
  33.             spin_lock(&hcd_root_hub_lock);
  34.         } else {
  35.             length = 0;
  36.             hcd->poll_pending = 1;
  37.         }
  38.         spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
  39.     }

  40.     /* The USB 2.0 spec says 256 ms. This is close enough and won



总计:usb的IN事务在此处变成了一个定时器的工作了,毕竟HC和roothub在出生的时候就绑在一起了;
现在回头看看,hub驱动的探测过程中hub_probe()中启动hub_configure(hub, endpoint)也就是唤醒timer;

至于hub_irq的调用:找了很久,没有整明白,可能又和ehci和系统之间的中断有关联了,避免问题太复杂,我这里引用fudan_abc的话:
我们曾经在hub_configure中讲过中断传输,当时调用了usb_fill_int_urb()函数,并且把hub_irq作为一个参数传递了进去,最终把urb->complete赋值为hub_irq.然后,主机控制器会定期询问hub,每当hub端口上有一个设备插入或者拔除时,它就会向主机控制器打小报告.。。。
(
具体来说,从硬件的角度看,就是hub会向host controller返回一些信息,或者说data,这个Data被称作”Hub and Port Status Change Bitmap”,而从软件角度来看,host controller的驱动程序接下来会在处理好这个过程的urb之后,调用该urbcomplete函数,对于hub来说,这个函数就是hub_irq().





阅读(3536) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~