老早听人讲,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()
/*-------------------------------------------------------------------------*/
-
static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
-
{
-
int retval;
-
unsigned long flags;
-
unsigned len = 1 + (urb->dev->maxchild / 8);
-
-
spin_lock_irqsave (&hcd_root_hub_lock, flags);
-
if (hcd->status_urb || urb->transfer_buffer_length < len) {
-
dev_dbg (hcd->self.controller, "not queuing rh status urb\n");
-
retval = -EINVAL;
-
goto done;
-
}
-
-
retval = usb_hcd_link_urb_to_ep(hcd, urb);
-
if (retval)
-
goto done;
-
-
hcd->status_urb = urb;
-
urb->hcpriv = hcd; /* indicate it
靠,搞不明白了:中断传输呢??
百度,再百度,在网上找到这么一句话,
Root Hub interrupt transfers are polled using a timer if the driver requests it;
也就是讲,roothub的中断传输,其实用个定时器,去访问HC的register;快晕菜了;
-
/*-------------------------------------------------------------------------*/
-
-
/*
-
* Root Hub interrupt transfers are polled using a timer if the
-
* driver requests it; otherwise the driver is responsible for
-
* calling usb_hcd_poll_rh_status() when an event occurs.
-
*
-
* Completions are called in_interrupt(), but they may or may not
-
* be in_irq().
-
*/
-
void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
-
{
-
struct urb *urb;
-
int length;
-
unsigned long flags;
-
char buffer[6]; /* Any root hubs with > 31 ports? */
-
-
if (unlikely(!hcd->rh_registered))
-
return;
-
if (!hcd->uses_new_polling && !hcd->status_urb)
-
return;
-
-
length = hcd->driver->hub_status_data(hcd, buffer);
-
if (length > 0) {
-
-
/* try to complete the status urb */
-
spin_lock_irqsave(&hcd_root_hub_lock, flags);
-
urb = hcd->status_urb;
-
if (urb) {
-
hcd->poll_pending = 0;
-
hcd->status_urb = NULL;
-
urb->actual_length = length;
-
memcpy(urb->transfer_buffer, buffer, length);
-
-
usb_hcd_unlink_urb_from_ep(hcd, urb);
-
spin_unlock(&hcd_root_hub_lock);
-
usb_hcd_giveback_urb(hcd, urb, 0);
-
spin_lock(&hcd_root_hub_lock);
-
} else {
-
length = 0;
-
hcd->poll_pending = 1;
-
}
-
spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
-
}
-
-
/* 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之后,调用该urb的complete函数,对于hub来说,这个函数就是hub_irq().
阅读(3550) | 评论(0) | 转发(0) |