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 hubhub_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 hubusb hub而言,usb_submit_urb(hub->urb)函数提交了一个usb中断传输请求块,之后,usb controler就主动的in包,用来启动一次中断传输。 
从而root hubhub_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 hubusb hubhub_irq是由于hc处理完事务而执行的

Logo

更多推荐