linux内核中USB总线的hub中断的调用
1)对于root hub的中断端点,在hub_probe中调用usb_hub_configure函数,而这个函数中设置了回调函数hub_irq: FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq, hub, endpoint->bInterval); 然后执行usb_submit_urb(hub->urb)函数,从
1)对于root hub的中断端点,在hub_probe中调用usb_hub_configure函数,而这个函数中设置了回调函数hub_irq:
FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
hub, endpoint->bInterval);
然后执行usb_submit_urb(hub->urb)函数,从而root hub的hub_irq函数通过定时器周期性的执行,即执行rh_int_timer_do => urb->complete (urb);因而通过中断端点可以检测到是否有设备插入。由于控制端点没有设置这个回调函数,所以rh_submit_urb (urb_t * urb)函数的最后两条语句也就不执行任何的回调函数。
2)而对于所有的usb设备,当处理完成一个事务时,hc_interrupt-----dl_done_list-----sohci_return_urb-----urb->complete (urb);的回调函数,根据不同的端点而执行不同的回调函数hub_irq或者是usb_api_blocking_completion
所以,对于root hub的中断端点有两处执行hub_irq的地方,一处是由于定时器而周期性的执行hub_irq,另一处是由于hc处理完事务又执行了一次;而非root hub的设备只用在处理完事务后才调用一次。
你看我这样理解还有什么问题没:
1)对于root hub的中断端点,在hub_probe中调用usb_hub_configure函数,而这个函数中设置了回调函数hub_irq:
FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
hub, endpoint->bInterval);
然后执行usb_submit_urb(hub->urb)函数,
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
上面理解的很对,但对于root hub的处理和其他的usb hub有所不同,他并不是真的提交这样的一个请求,因为root hub 和 usb controler集成在一起,所以没有必要真正的启动一次中断传输。而在这个情境中,usb_submit_urb(hub->urb)其实就是static int sohci_submit_urb (urb_t * urb),由于我们提交的是一个root hub的传输请求块,所以,具体的执行是rh_submit_urb (urb)函数,你可以具体看一看这个函数。
对于其他的非root hub的usb hub而言,usb_submit_urb(hub->urb)函数提交了一个usb中断传输请求块,之后,usb controler就主动的in包,用来启动一次中断传输。
从而root hub的hub_irq函数通过定时器周期性的执行,即执行rh_int_timer_do => urb->complete (urb);因而通过中断端点可以检测到是否有设备插入。由于控制端点没有设置这个回调函数,所以rh_submit_urb (urb_t * urb)函数的最后两条语句也就不执行任何的回调函数。
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
不对,hub_irq不会因为设定的定时器而周期的执行,只有端口状态变化才执行,在rh_submit_urb (urb)中表述的很清楚
if (usb_pipeint(pipe)) {-------------------如果是一个中断的pipe,那么执行进入
ohci->rh.urb = urb;
ohci->rh.send = 1;
ohci->rh.interval = urb->interval;
rh_init_int_timer(urb);------------初始化timer
urb->status = cc_to_error [TD_CC_NOERROR];
return 0;-------------------------返回
}
,我们可以看一下这个初始化timer的函数
static int rh_init_int_timer (urb_t * urb)
{
ohci_t * ohci = urb->dev->bus->hcpriv;
ohci->rh.interval = urb->interval;
init_timer (&ohci->rh.rh_int_timer);
ohci->rh.rh_int_timer.function = rh_int_timer_do;-------------timer到期后执行的函数
ohci->rh.rh_int_timer.data = (unsigned long) urb;------------传递一个urb参数
ohci->rh.rh_int_timer.expires =
jiffies + (HZ * (urb->interval < 30? 30: urb->interval)) / 1000;
add_timer (&ohci->rh.rh_int_timer);------------启动timer
return 0;
}
我们再看一下timer到期的函数
static void rh_int_timer_do (unsigned long ptr)
{
int len;
urb_t * urb = (urb_t *) ptr;
ohci_t * ohci = urb->dev->bus->hcpriv;
if (ohci->disabled)
return;
/* ignore timers firing during PM suspend, etc */
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER)
goto out;
if(ohci->rh.send) {
下面这个函数将检测该root hub的端口的状态,如果端口状态发生变化,则执行下面的urb->complete (urb);
len = rh_send_irq (ohci, urb->transfer_buffer, urb->transfer_buffer_length);
if (len > 0) {
urb->actual_length = len;
#ifdef DEBUG
urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe));
#endif
if (urb->complete)
urb->complete (urb);
}
}
out:
rh_init_int_timer (urb);-------重设timer
}
2)而对于所有的usb设备,当处理完成一个事务时,hc_interrupt-----dl_done_list-----sohci_return_urb-----urb->complete (urb);的回调函数,根据不同的端点而执行不同的回调函数hub_irq或者是usb_api_blocking_completion
所以,对于root hub的中断端点有两处执行hub_irq的地方,一处是由于定时器而周期性的执行hub_irq,另一处是由于hc处理完事务又执行了一次;而非root hub的设备只用在处理完事务后才调用一次。
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
不是,对于root hub而言,hub_irq是通过timer来执行的,因为集成在一起,所以如果也启动一次中断传输会显得是那么的愚蠢,而对于其他的非root hub的usb hub,hub_irq是由于hc处理完事务而执行的
更多推荐
所有评论(0)