9.不一样的Core
我们来看Core目录。关于USB,有一个很重要的模块,它的名字耐人寻味——usbcore。如果你的电脑安装了Linux操作系统,那么你用lsmod命令查看,有一个模块叫做usbcore。当然,你要是玩嵌入式系统的高手,那么也许你的电脑里没有USB模块。不过听说如今玩嵌入式的人也喜欢玩USB,因为USB设备很符合嵌入式的口味。查看lsmod命令的输出吧。
localhost:/usr/src/linux-2.6.22.1/drivers/usb/core # lsmod Module Size Used by af_packet 55820 2 raw 89504 0 nfs 230840 2 lockd 87536 2 nfs nfs_acl 20352 1 nfs sunrpc 172360 4 nfs,lockd,nfs_acl ipv6 329728 36 button 24224 0 battery 27272 0 ac 22152 0 apparmor 73760 0 aamatch_pcre 30720 1 apparmor loop 32784 0 usbhid 60832 0 dm_mod 77232 0 ide_cd 57120 0 hw_random 22440 0 ehci_hcd 47624 0 cdrom 52392 1 ide_cd uhci_hcd 48544 0 shpchp 61984 0 bnx2 157296 0 usbcore 149288 4 usbhid,ehci_hcd,uhci_hcd e1000 130872 0 pci_hotplug 44800 1 shpchp reiserfs 239616 2 edd 26760 0 fan 21896 0 thermal 32272 0 processor 50280 1 thermal qla2xxx 149484 0 firmware_class 27904 1 qla2xxx scsi_transport_fc 51460 1 qla2xxx sg 52136 0 megaraid_sas 47928 3 piix 27652 0 [permanent] sd_mod 34176 4 scsi_mod 163760 5 qla2xxx,scsi_transport_fc,sg,megaraid_sas,sd_mod ide_disk 32768 0 ide_core 164996 3 ide_cd,piix,ide_disk
找到usbcore那一行了吗?它就是这里要说的USB子系统的核心,如果要在Linux里使用USB,这个模块是必不可少的,另外,你应该会在usbcore的最后一行看到ehci_hcd或uhci_hcd,它们就是前面说的USB主机控制器的驱动模块,你的USB设备要工作,合适的USB主机控制器模块也是必不可少的。
USB Core负责实现一些核心的功能,为别的设备驱动程序提供服务,提供一个用于访问和控制USB硬件的接口,而不用去考虑系统当前存在哪种主机控制器。至于USB Core、USB主机控制器和USB设备驱动三者之间的关系,如图1.9.1所示。
图1.9.1 内核中USB子系统的结构
驱动和主机控制器像不像Core的两个保镖?没办法,这可是Core啊!协议中也说了,主机控制器的驱动(HCD)必须位于USB软件的最下一层。HCD提供主机控制器硬件的抽象,隐藏硬件的细节,在主机控制器之下是物理的USB及所有与之连接的USB设备。而HCD只有一个客户,对一个人负责,就是咱们的USB Core,USB Core将用户的请求映射到相关的HCD,用户不能直接访问HCD。
在写USB驱动时,只能调用Core的接口,Core会将咱们的请求发送给相应的HCD,Core为咱们完成了大部分的工作,Linux的哲学是不是和咱们生活中不太一样?
到drivers/usb/core目录里,使用ls命令看一看。
Kconfig Makefile buffer.c config.c devices.c devio.c driver.c endpoint.c file.c generic.c hcd-pci.c hcd.c hcd.h hub.c hub.h inode.c message.c notify.c otg_whitelist.h quirks.c sysfs.c urb.c usb.c usb.h
再使用wc命令统计,将近两万行的代码,Core不愧是Core,为大家默默地做这么多事,我们要用感恩的心去深刻理解你的内心,回报你的付出。
不过这么多文件中不一定都是我们所要关注的,先拿咱们的地图来看一看接下来该怎么走。先看一看Kconfig文件。
4 config USB_DEBUG 5 bool "USB verbose debug messages" 6 depends on USB 7 help 8 Say Y here if you want the USB core & hub drivers to produce a bunch 9 of debug messages to the system log. Select this if you are having a 10 problem with USB support and want to see more of what is going on.
这是USB的调试tag,如果你在写USB设备驱动的话,最好还是打开它吧,不过这里它就不是我们关注的重点了。
15 config USB_DEVICEFS 16 bool "USB device filesystem" 17 depends on USB 18 ---help--- 19 If you say Y here (and to "/proc file system support" in the "File 20 syste ms" section, above), you will get a file /proc/bus/usb/devices 21 which lists the devices currently connected to your USB bus or 22 busses, and for every connected device a file named 23 "/proc/bus/usb/xxx/yyy", where xxx is the bus number and yyy the 24 device number; the latter files can be used by user space progra ms 25 to talk directly to the device. These files are "virtual", meaning 26 they are generated on the fly and not stored on the hard drive. 27 28 You may need to mount the usbfs file system to see the files, use 29 mount -t usbfs none /proc/bus/usb 30 31 For the format of the various /proc/bus/usb/ files, please read 32 <file:Documentation/usb/proc_usb_info.txt>. 33 34 Usbfs files can't handle Access Control Lists (ACL), which are the 35 default way to grant access to USB devices for untrusted users of a 36 desktop system. The usbfs functionality is replaced by real 37 device-nodes managed by udev. These nodes live in /dev/bus/usb and 38 are used by libusb.
这个选项是关于usbfs文件系统的。usbfs文件系统挂载在/proc/bus/usb上(mount -t usbfs none /proc/bus/usb),显示了当前连接的USB设备及总线的各种信息,每个连接的USB设备在其中都会有一个文件进行描述。比如文件/proc/bus/usb/xxx/yyy,xxx表示总线的序号,yyy表示设备在总线的地址,不过不能够依赖它们来稳定地访问设备,因为同一个设备两次连接对应的描述文件可能会不同。比如,第一次连接一个设备时,它可能是002/027,一段时间后再次连接,它可能就已经改变为002/048。
usbfs与咱们探讨的主题关系不大,况且也已经足可以开个专题来讨论了,所以以后不会过多地提及它。
74 config USB_SUSPEND 75 bool "USB selective suspend/resume and wakeup (EXPERIMENTAL)" 76 depends on USB && PM && EXPERIMENTAL 77 help 78 If you say Y here, you can use driver calls or the sysfs 79 "power/state" file to suspend or resume individual USB 80 peripherals. 81 82 Also, USB "remote wakeup" signaling is supported, whereby some 83 USB devices (like keyboards and network adapters) can wake up 84 their parent hub. That wakeup cascades up the USB tree, and 85 could wake the system from states like suspend-to-RAM. 86 87 If you are unsure about this, say N here.
这一项有关USB设备的挂起和恢复。开发USB的人都是节电节能的好孩子,所以协议中就规定了:所有设备都必须支持挂起状态,也就是说,为了达到节电的目的,当设备在指定的时间内(3ms),如果没有发生总线传输,就要进入挂起状态。当它收到一个non-idle的信号时,就会被唤醒,节约用电从USB做起。不过目前来说,内核对挂起休眠的支持普遍都不太好,而且许多USB设备也没有支持它,还是暂且不提了。
剩下的还有几项,不过似乎与咱们关系也不大,还是去看一看Makefile。
5 usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \ 6 config.o file.o buffer.o sysfs.o endpoint.o \ 7 devio.o notify.o generic.o quirks.o 8 9 ifeq ($(CONFIG_PCI),y) 10 usbcore-objs += hcd-pci.o 11 endif 12 13 ifeq ($(CONFIG_USB_DEVICEFS),y) 14 usbcore-objs += inode.o devices.o 15 endif 16 17 obj-$(CONFIG_USB) += usbcore.o 18 19 ifeq ($(CONFIG_USB_DEBUG),y) 20 EXTRA_CFLAGS += -DDEBUG 21 endif
Makefile可比Kconfig简略多了,所以看起来也更亲切,咱们总是拿的钱越多越好,看的代码越少越好。这里之所以会出现CONFIG_PCI,是因为USB的Root Hub通常包含在一个PCI设备中,前面也已经聊过了。hcd-pci和hcd顾名思义就是主机控制器,它们实现了主机控制器公共部分,按协议中的说法,它们就是HCDI(HCD的公共接口),host目录下则实现了各种不同的主机控制器。CONFIG_USB_DEVICEFS在前面的Kconfig文件中也见到了,关于usbfs,与咱们的主题无关,inode.c和devices.c两个文件也可以不用管了。