linux usb hub driver,Linux下的USB HUB驱动

Linux下的USB HUB驱动

[日期:2012-07-29]

来源:Linux社区

作者:zhengmeifu

[字体:大 中 小]

在这里,顺带提一下HUB的指示灯问题.

Hub描述符的wHubCharacteristics的bit7来描述设备是否支持显示灯.为1表示在下游的连接端口上支持显示灯,为0则不支持.

如果Hub支持指示灯,则将hub->has_indicators置为1.另外,HUB的指示灯是否起作用,还由一个参数决定,在代码中,大家也看到,这个参数是blinkenlights.这个参数定义如下:

static int blinkenlights = 0;

module_param (blinkenlights, bool, S_IRUGO);

MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs");

这是一个可调的模块参数.如果要显示灯起作用,必须要将其置为1才可以.我们可以用下面两种方法来设置这个参数:

1:如果模块没有编译进kernel,可以在插入模块的时候,加上这个参数:

modprobe usbcore blinkenlights=1

2:如果模块已经编进kernel,那在kernel的启动参数上加上如下参数:

usbcore.blinkenlights=1

在usb2.0 spec中,对不同情况下的灯颜色都做了定义.

在代码中,灯的显示交给了一延迟的工作队列进行处理,初始化如下所示:

INIT_DELAYED_WORK(&hub->leds, led_work); (在hub_probe()函数中)

在这里,并不打算详细分析这一部份,有兴趣的可以跟踪下去看下.

那函数后面初始化的URB是用来干什么的呢?我们将这个URB的初始化部份单独列出如下:

pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress);

maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));

if (maxp > sizeof(*hub->buffer))

maxp = sizeof(*hub->buffer);

我们从此可以看出,这个URB是作用于ep0之外的另一个端点,而且传输数据的长度最大为sizeof(*hub->buffer)

Hub->buffer被定义如下:

struct usb_hub {

……

char            (*buffer)[8];

……

}

由此可以看出buffer是指向一个8元素字符数组的指针,sizeof(*hub->buffer)等于0.

关于传输的数据长度,代码中有一段注释,这段注释说,spec上规定的长度是(PORTS+1+7)/8.而linux中,对每个hub上挂有认为最多的端口进行处理,因些,就是(31+1+7)/8 = 5

为什么这里要是8呢?

因为usb2.0 spec上规定,ep0的最大发包长度,可能为8.16.32.64.512.所以选择比5要大的最小值8.

另外,我们注意到,URB完成之后,所要调用的函数是hub_irq().如下所示:

usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq,

hub, endpoint->bInterval);

UHCI必须要知道HUB的端口的一些连接状态,因此,需要HUB周期性的上报它的端口连接状态.这个URB就是用来做这个用途的.UHCI周期性的发送IN方向中断传输传输给HUB.HUB就会通过这个URB将端口信息发送给HUB.

那这个轮询周期是多长呢?根据我们之前分析的UHCI的知识,它的调度周期是由endpoint的bInterval 字段所决定的.

现在,我们慢慢来接触到hub的一些核心处理了.整理一下心情,继续看代码.^_^

接下来,我们要看到的第一个函数是hub_power_on().代码如下:

static void hub_power_on(struct usb_hub *hub)

{

int port1;

//从连接端口从开机到准备好的时间

unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;

//wHubCharacteristics字段

u16 wHubCharacteristics =

le16_to_cpu(hub->descriptor->wHubCharacteristics);

/* Enable power on each port.  Some hubs have reserved values

* of LPSM (> 2) in their descriptors, even though they are

* USB 2.0 hubs.  Some hubs do not implement port-power switching

* but only emulate it.  In all cases, the ports won't work

* unless we send these messages to the hub.

*/

//开关模式

if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2)

dev_dbg(hub->intfdev, "enabling power on all ports\n");

else

dev_dbg(hub->intfdev, "trying to enable port power on "

"non-switchable hub\n");

//给每一个端口发送PORT_POWER的Set_Feature消息

for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)

set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);

/* Wait at least 100 msec for power to become stable */

//等待端口可以正常工作,至少100 ms

msleep(max(pgood_delay, (unsigned) 100));

}

这里就是给每个接口发送PORT_POWER的Set_Feature消息,告之可起来工作了,然后等待端口可以工作.

另外要分析的函数是hub_activate().代码如下:

static void hub_activate(struct usb_hub *hub)

{

int status;

hub->quiescing = 0;

hub->activating = 1;

//提交urb

status = usb_submit_urb(hub->urb, GFP_NOIO);

if (status < 0)

dev_err(hub->intfdev, "activate --> %d\n", status);

if (hub->has_indicators && blinkenlights)

schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);

/* scan all ports ASAP */

kick_khubd(hub);

}

首先,是在hub的两个字段进行赋值操作,hub-> quiescing 和 hub->activating表示分别表示hub处理暂停和活跃状态.注意,在这里,不要和接口的mark_active()设置的intf->is_active相混淆.

然后,将hub->urb提交.开始调度Led的工作队列.

最后,流程转入kick_khubd().代码如下:

static void kick_khubd(struct usb_hub *hub)

{

unsigned long   flags;

/* Suppress autosuspend until khubd runs */

//pm_usage_cnt设置为1,防止autosuspend

to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;

spin_lock_irqsave(&hub_event_lock, flags);

if (!hub->disconnected && list_empty(&hub->event_list)) {

list_add_tail(&hub->event_list, &hub_event_list);

wake_up(&khubd_wait);

}

spin_unlock_irqrestore(&hub_event_lock, flags);

}

在这个函数中,先将接口的pm_usage_cnt置1,此后,该接口就不能SUSPEND.

然后,将该hub添加进hub_event_list链表,并唤醒Khubd_wait等待队列.

hub_event_list和Khubd_wait到底代表着什么呢?它后面的参数又是什么呢?接着往下看0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值