莎士比亚曾经说过,不懂hub是怎么工作的就等于不知道usb设备驱动是怎么工作的.这句话一点没错,因为usb设备的初始化都是hub这边发起的,通常我们写usb设备驱动程序都是在已经得到了一个struct usb_interface指针的情况下开始probe工作,可是我要问你,你的struct usb_interface从哪来的?你以为你的设备天生丽质?长得比较帅?一插入usb口就有了?如果有人说是的,那么我只能说,相信这个人的嘴,不如相信世上有鬼!老实说,要想知道从usb设备插入usb口的那一刻开始,这个世界发生了什么,你必须知道hub是怎么工作的,Linux中hub驱动程序是怎么工作的.
要说usb hub,那得从Root hub说起.什么是Root hub?冤有头债有主,不管你的电脑里连了多少个usb设备,她们最终是有根的,她们不会像孙猴那样从石头里蹦出来的,不会像北京电视台纸包子的新闻凭空就可以造出来.所有的usb设备最终都是连接到了一个叫做Root Hub的冬冬上,或者说所有的根源都是从这里开始的.Root Hub上可以连接别的设备,可以连接U盘,可以连接usb鼠标,同样也可以连接另一个hub.所谓hub,就是用来级连.但是普通的hub,她一头接上级hub, 另一头可以有多个口,多个口就可以级连多个设备,也可以只有一个口,一个口的就像我们宿舍里常用的那种延长线.而Root Hub呢?她比较特殊,她当然也是一种usb设备,但是她属于一人之下万人之上的角色,她只属于被Host Controller,换言之,通常做芯片的同志们会把Host Controller和Root Hub集成在一起.特别是PC主机上,通常你就只能看到接口,看不到Root Hub,因为她躺在Host Controller的怀里.这一对狗男女躲在机箱里面,你当然看不到.下面这张图看得很清楚,
其中的那个host hub其实就是root hub.当然,我们应该更加准备的评价host和root hub的关系,她们是双生花,不会残酷地吸纳彼此的幸福,只会一直不离不弃地在风中相依,直到凋零…(虽然言论自由,但是我必须声明,我绝对没有影射最近牺牲在车里的徐新贤书记以及那个和他一起裸死在车里的妇联主席潘丽航的意思,请不要误会,我个人还是很欣赏这种死了都要爱的境界的,这种追求真爱,追求自由的思想正是整个开源社区所推崇的,也正是开源精神的灵魂所在,我顶!)
Ok,别扯远了,继续回来,既然root hub享有如此特殊的地位,那么很显然,整个usb子系统得特别的爱给特别的你,一开始就会要初始化hub.所以我们从usb子系统的初始化代码开始看起.也就是usb的核心代码.来自drivers/usb/core/usb.c:
938 subsys_initcall(usb_init);
939 module_exit(usb_exit);
很显然,这样两行正是Linux中usb子系统的初始化代码,这里我们看到一个subsys_initcall,它也是一个宏,我们可以把它理解为module_init,只不过因为这部分代码比较核心,开发者们把它看作一个子系统,而不仅仅是一个模块,这也很好理解,usbcore这个模块它代表的不是某一个设备,而是所有usb设备赖以生存的模块,Linux中,像这样一个类别的设备驱动被归结为一个子系统.比如pci子系统,比如scsi子系统,基本上,drivers/目录下面第一层的每个目录都算一个子系统,因为它们代表了一类设备.subsys_initcall(usb_init)的意思就是告诉我们usb_init是我们真正的初始化函数,而usb_exit()将是整个usb子系统的结束时的清理函数.于是我们就从usb_init开始看起,
860 /*
861 * Init
862 */
863 static int __init usb_init(void)
864 {
865 int retval;
866 if (nousb) {
867 pr_info("%s: USB support disabled/n", usbcore_name);
868 return 0;
869 }
870
871 retval = ksuspend_usb_init();
872 if (retval)
873 goto out;
874 retval = bus_register(&usb_bus_type);
875 if (retval)
876 goto bus_register_failed;
877 retval = usb_host_init();
878 if (retval)
879 goto host_init_failed;
880 retval = usb_major_init();
881 if (retval)
882 goto major_init_failed;
883 retval = usb_register(&usbfs_driver);
884 if (retval)
885 goto driver_register_failed;
886 retval = usb_devio_init();
887 if (retval)
888 goto usb_devio_init_failed;
889 retval = usbfs_init();
890 if (retval)
891 goto fs_init_failed;
892 retval = usb_hub_init();
893 if (retval)
894 goto hub_init_failed;
895 retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
896 if (!retval)
897 goto out;
898
899 usb_hub_cleanup();
900 hub_init_failed:
901 usbfs_cleanup();
902 fs_init_failed:
903 usb_devio_cleanup();
904 usb_devio_init_failed:
905 usb_deregister(&usbfs_driver);
906 driver_register_failed:
907 usb_major_cleanup();
908 major_init_failed:
909 usb_host_cleanup();
910 host_init_failed:
911 bus_unregister(&usb_bus_type);
912 bus_register_failed:
913 ksuspend_usb_cleanup();
914 out:
915 return retval;
916 }
2854 int usb_hub_init(void)
2855 {
2856 if (usb_register(&hub_driver) < 0) {
2857 printk(KERN_ERR "%s: can't register hub driver/n",
2858 usbcore_name);
2859 return -1;
2860 }
2861
2862 khubd_task = kthread_run(hub_thread, NULL, "khubd");
2863 if (!IS_ERR(khubd_task))
2864 return 0;
2865
2866 /* Fall through if kernel_thread failed */
2867 usb_deregister(&hub_driver);
2868 printk(KERN_ERR "%s: can't start khubd/n", usbcore_name);
2869
2870 return -1;
2871 }
最后,补充一条背景知识介绍,本年度感动中国新闻之一:
杭州信息网最新消息:临安市清凉峰镇党委书记,优秀共产党员徐新贤日前因公牺牲.徐新贤书记因忙于公务,日夜操劳过度,终因体力不支,牺牲在小车上,同时牺牲的还有该镇优秀妇女干部一名.据悉,徐新贤书记和该名妇女干部在小汽车里谈论公务,因汽油燃尽,空调断电,车内闷热严重,车子又是停在车库里,二人为了解热,脱光了衣服裤子,还在坚持谈公事,一直谈到牺牲为止.有这样认真负责的好书记,清凉峰镇的老百姓是幸福的.书记时刻为人民办事,牺牲前还在亲自做妇女工作,他的事迹,人们都记在了心里.
一路走来的兄弟们不会对这样一段代码陌生,是不是有一种似曾相识燕归来的感觉?没有?没有就没有吧,同是天涯堕落人,相逢何必曾相识.好家伙,一堆的函数,每一个都够我看的了.写代码的无非就是想吓唬吓唬我,共产党员死都不怕,这点小事还能吓住我们吗? 我们不用仔细看,扫一眼就能发现,许多名叫*init*的函数,很显然,就是做一些初始化.其中我们要关注的是hub,它也是在这里初始化的,换言之,随着usb core的初始化,hub也就开始了她的初始化之路.这就是1490行,usb_hub_init()函数得到调用.这个函数来自drivers/usb/core/hub.c: