赞
踩
初始化
谨以此文纪念过往的岁月
一.前言
在上文中讲述了usb子系统的初始化,在该文中来看usb hub的驱动。不过在这里需要说明一点,host controller和usb hub是不同的东西。hc是指usb的控制器,而hub是一种usb集线器,其本质还是一种usb设备,只不过这种usb设备有点特殊而已。一般的MCU都会自带一个usb hub,以s3c6410为例,其带有一个hub,该hub有两个下行口,就是俗话所说的两个usb接口。你可以在把两个usb设备插到该hub下,再多就不行了。而该hub就是传说中的root hub,以该root hub为例,如果在该hub下还挂载一个hub,那插入的hub不是root hub而是一个hub设备,对于linux而言其会为每一个hub创建一条总线,用于该hub下的设备与驱动绑定。对于一般系统而言,一般一个hc对应一个root hub。
二.hub设备
关于root hub的设备注册还记否,在上文OHCI中已经涉及到了,不过特意点明而已,就是在register_root_hub中。
三.hub驱动
usb hub其实也是一种usb设备,其驱动不脱离usb驱动的模板。在usb_init中会调用usb_hub_init函数来注册hub的驱动。usb_register(&hub_driver),注册一个hub驱动。
那下面来看该hub_driver的具体每一个函数。
static struct
usb_driver hub_driver = {
.name ="hub",
.probe =hub_probe,
.disconnect =hub_disconnect,
.suspend =hub_suspend,
.resume =hub_resume,
.reset_resume =hub_reset_resume,
.pre_reset =hub_pre_reset,
.post_reset =hub_post_reset,
.ioctl =hub_ioctl,
.id_table =hub_id_table,
.supports_autosuspend =1,
};
2.1 hub_probe
hub探测函数,在驱动注册或设备注册时会调用。
static int
hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_host_interface *desc;
struct usb_endpoint_descriptor
*endpoint;
struct usb_device *hdev;
struct usb_hub *hub;
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
if (hdev->level == MAX_TOPO_LEVEL) { --只只支持六层嵌套,就是所谓的hub接hub,最多接六层。
return -E2BIG;
}
if ((desc->desc.bInterfaceSubClass
!= 0) && (desc->desc.bInterfaceSubClass != 1)) {--一些湖北的subclass
= 1。根据usb的spec这是不允许的不过这还是可以工作的的,这世界总有些特殊的嘛,即是在协议界。
descriptor_error:
return -EIO;
}
if (desc->desc.bNumEndpoints != 1)--记住hub的端点只能有一个!!
goto descriptor_error;
endpoint = &desc->endpoint[0].desc;
if (!usb_endpoint_is_int_in(endpoint))--而且这个端点还必须是中断in类型。
goto descriptor_error;
hub = kzalloc(sizeof(*hub),
GFP_KERNEL); --在上述情况都满足的情况下才能说有一个hub存在。
if (!hub) {
return -ENOMEM;
}
kref_init(&hub->kref);--hub参数的初始化。
INIT_LIST_HEAD(&hub->event_list);
--事件链表,每一次的插拔都会引起hub的中断。会将该链表添加到hub_event_list链表中,同时唤醒khubd_wait即hub守护程序。
hub->intfdev = &intf->dev;--接口设备
hub->hdev = hdev;--hub的实体。
(&hub->leds,
led_work);
INIT_DELAYED_WORK(&hub->init_work,
NULL);
usb_get_intf(intf);
usb_set_intfdata (intf, hub);
intf->needs_remote_wakeup = 1;
if (hdev->speed == USB_SPEED_HIGH)
highspeed_hubs++;
if ((hub,
endpoint) >= 0)
return 0;
hub_disconnect (intf);
return -ENODEV;
}
的实例后,就需要对hub的配置。你会发现这是一个巨大的函数,不要畏惧其的巨大,还是一如既往的去分析他吧!
static int hub_configure(struct
usb_hub *hub,struct usb_endpoint_descriptor *endpoint)
{
struct usb_device *hdev = hub->hdev;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。