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

Linux下的USB HUB驱动

[日期:2012-07-29]

来源:Linux社区

作者:zhengmeifu

[字体:大 中 小]

接下来,就要对设备进行配置了,首先,将设备唤醒.回忆一下我们在分析UHCI驱动时,列出来的设备状态图.只有在ADDRESS状态才能转入到CONFIG状态.(SUSPEND状态除外). 所以,如果设备当前不是处于ADDRESS状态,就需要将设备的状态初始化.usb_disable_device()函数是个比较重要的操作,在接下来再对它进行详细分析.

接着,发送SET_CONFIGURATION的Control消息给设备,用来选择配置

最后,将dev->actconfig指向选定的配置,将设备状态设为CONFIG

/* Initialize the new interface structures and the

* hc/hcd/usbcore interface/endpoint state.

*/

//遍历所有的接口

for (i = 0; i < nintf; ++i) {

struct usb_interface_cache *intfc;

struct usb_interface *intf;

struct usb_host_interface *alt;

cp->interface[i] = intf = new_interfaces[i];

intfc = cp->intf_cache[i];

intf->altsetting = intfc->altsetting;

intf->num_altsetting = intfc->num_altsetting;

//是否关联的接口描述符,定义在minor usb 2.0 spec中

intf->intf_assoc = find_iad(dev, cp, i);

kref_get(&intfc->ref);

//选择0号设置

alt = usb_altnum_to_altsetting(intf, 0);

/* No altsetting 0?  We'll assume the first altsetting.

* We could use a GetInterface call, but if a device is

* so non-compliant that it doesn't have altsetting 0

* then I wouldn't trust its reply anyway.

*/

//如果0号设置不存在,选排在第一个设置

if (!alt)

alt = &intf->altsetting[0];

//当前的配置

intf->cur_altsetting = alt;

usb_enable_interface(dev, intf);

intf->dev.parent = &dev->dev;

intf->dev.driver = NULL;

intf->dev.bus = &usb_bus_type;

intf->dev.type = &usb_if_device_type;

intf->dev.dma_mask = dev->dev.dma_mask;

device_initialize(&intf->dev);

mark_quiesced(intf);

sprintf(&intf->dev.bus_id[0], "%d-%s:%d.%d",

dev->bus->busnum, dev->devpath,

configuration, alt->desc.bInterfaceNumber);

}

kfree(new_interfaces);

if (cp->string == NULL)

cp->string = usb_cache_string(dev, cp->desc.iConfiguration);

之前初始化的new_interfaces在这里终于要派上用场了.初始化各接口,从上面的初始化过程中,我们可以看出:

Intf->altsetting,表示接口的各种设置

Intf->num_altsetting:表示接口的设置数目

Intf->intf_assoc:接口的关联接口(定义于minor usb 2.0 spec)

Intf->cur_altsetting:接口的当前设置.

结合之前在UHCI中的分析,我们总结一下:

Usb_dev->config,其实是一个数组,存放设备的配置.usb_dev->config[m]-> interface[n]表示第m个配置的第n个接口的intercace结构.(m,n不是配置序号和接口序号 *^_^*).

注意这个地方对intf内嵌的struct devcie结构赋值,它的type被赋值为了usb_if_device_type.bus还是usb_bus_type.可能你已经反应过来了,要和这个device匹配的设备是interface的驱动.

特别的,这里的device的命名:

sprintf(&intf->dev.bus_id[0], "%d-%s:%d.%d",

dev->bus->busnum, dev->devpath,

configuration, alt->desc.bInterfaceNumber);

dev指的是这个接口所属的usb_dev,结合我们之前在UHCI中关于usb设备命名方式的描述.可得出它的命令方式如下:

USB总线号-设备路径:配置号.接口号.

例如,在我的虚拟机上:

[root@localhost devices]# pwd

/sys/bus/usb/devices

[root@localhost devices]# ls

1-0:1.0  usb1

[root@localhost devices]#

可以得知,系统只有一个usb control.

1-0:1.0:表示,第一个usb control下的root hub的1号配置的0号接口.

那在插入U盘之后,会发生什么变化呢?不着急,我们等着往下面看,待分析到的时候,我自然就会列出来了 ^_^

usb_enable_interface()用来启用接口,也就是启用接口中的每一个endpoint.这个接口比较简单,其中调用的子函数usb_enable_endpoint()在分析UHCI的时候已经详细分析过了.在这里就不再赘述了.

在这里,还涉及到一个很有意思的函数, mark_quiesced().从字面意思上看来,它是标记接口为停止状态.它的”反函数”是mark_active().两个函数如下示:

static inline void mark_active(struct usb_interface *f)

{

f->is_active = 1;

f->dev.power.power_state.event = PM_EVENT_ON;

}

static inline void mark_quiesced(struct usb_interface *f)

{

f->is_active = 0;

f->dev.power.power_state.event = PM_EVENT_SUSPEND;

}

从代码看来,它只是对接口的活动标志(is_active)进行了设置.

/* Now that all the interfaces are set up, register them

* to trigger binding of drivers to interfaces.  probe()

* routines may install different altsettings and may

* claim() any interfaces not yet bound.  Many class drivers

* need that: CDC, audio, video, etc.

*/

//注册每一个接口?

for (i = 0; i < nintf; ++i) {

struct usb_interface *intf = cp->interface[i];

dev_dbg(&dev->dev,

"adding %s (config #%d, interface %d)\n",

intf->dev.bus_id, configuration,

intf->cur_altsetting->desc.bInterfaceNumber);

ret = device_add(&intf->dev);

if (ret != 0) {

dev_err(&dev->dev, "device_add(%s) --> %d\n",

intf->dev.bus_id, ret);

continue;

}

usb_create_sysfs_intf_files(intf);

}

//使设备suspend

usb_autosuspend_device(dev);

return 0;

}

最后,注册intf内嵌的device结构.设备配置完成了,为了省电,可以将设备置为SUSPEND状态.0b1331709591d260c1c78e86d0c51c18.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值