您的位置:首页 > 运维架构 > Linux

linux内核中USB总线的hub中断的调用

2012-09-24 15:58 363 查看
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处理完事务而执行的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: