详解linux usb host驱动编写入门
usb协议是一个复杂的协议,目前涉及到的版本就有usb1.0,usb2.0,usb3.0。大家如果打开kernelusbhost目录,就会发现下面包含了ohci,uhci,ehci,xhci,whci等多种形式的控制器驱动。那么,对于我们这些不是很了解usb的开发人员,如何了解usb的代码结构呢?
1、代码分布
drivers/usb目录下面,host目录包括了host驱动代码,core目录包含了主要的api接口代码,而其他目录则主要是device驱动代码。
2、device驱动怎么看
device驱动大多数和上层协议有关,不涉及到具体的寄存器读写。示例代码可以参考usb-skeleton.c
3、host驱动怎么看
a,不妨以s3c2410的host作为范例进行分析,首先找到Makefile,
obj-$(CONFIG_USB_OHCI_HCD_S3C2410)+=ohci-s3c2410.o
b,再查看一下Kconfig,
configUSB_OHCI_HCD_S3C2410 tristate"OHCIsupportforSamsungS3C24xx/S3C64xxSoCseries" dependsonUSB_OHCI_HCD&&(ARCH_S3C24XX||ARCH_S3C64XX) defaulty ---help--- Enablessupportfortheon-chipOHCIcontrolleron S3C24xx/S3C64xxchips.
c,通过Makefile和Kconfig发现,s3c2410依赖于USB_OHCI_HCD_S3C2410和USB_OHCI_HCD,那USB_OHCI_HCD呢?
configUSB_OHCI_HCD tristate"OHCIHCD(USB1.1)support" dependsonHAS_DMA&&HAS_IOMEM ---help--- TheOpenHostControllerInterface(OHCI)isastandardforaccessing USB1.1hostcontrollerhardware.ItdoesmoreinhardwarethanIntel's UHCIspecification.IfyourUSBhostcontrollerfollowstheOHCIspec, sayY.Onmostnon-x86systems,andonx86hardwarethat'snotusinga USBcontrollerfromIntelorVIA,thisisappropriate.Ifyourhost controllerdoesn'tusePCI,thisisprobablyappropriate.ForaPCI basedsystemwhereyou'renotsure,the"lspci-v"entrywilllistthe right"prog-if"foryourUSBcontroller(s):EHCI,OHCI,orUHCI. Tocompilethisdriverasamodule,chooseMhere:the modulewillbecalledohci-hcd.
d,USB_OHCI_HCD只依赖于DMA和IOMEM。继续回到Makefile,判断USB_OHCI_HCD会编译哪些文件
obj-$(CONFIG_USB_OHCI_HCD)+=ohci-hcd.o
e,看到这里,我们明白要打开s3c2410的host功能,只需要编译ohci-hcd.c和ohci-s3c2410.c两个文件就好了
f,通过观察,发现ohci-hcd.c和ohci-s3c2410.c的代码都很少,这原因是什么?下面这段代码来自于ohci-hcd.c。
staticconstcharhcd_name[]="ohci_hcd"; #defineSTATECHANGE_DELAYmsecs_to_jiffies(300) #defineIO_WATCHDOG_DELAYmsecs_to_jiffies(275) #defineIO_WATCHDOG_OFF0xffffff00 #include"ohci.h" #include"pci-quirks.h" staticvoidohci_dump(structohci_hcd*ohci); staticvoidohci_stop(structusb_hcd*hcd); staticvoidio_watchdog_func(structtimer_list*t); #include"ohci-hub.c" #include"ohci-dbg.c" #include"ohci-mem.c" #include"ohci-q.c"
g,通过观察ohci-hcd.c文件,发现其实它其实已经包括了很多其他的ohci文件。那么寄存器又是怎么操作的呢?下面这段代码来自于ohci.h文件。
staticinlineunsignedint_ohci_readl(conststructohci_hcd*ohci, __hc32__iomem*regs) { #ifdefCONFIG_USB_OHCI_BIG_ENDIAN_MMIO returnbig_endian_mmio(ohci)? readl_be(regs): readl(regs); #else returnreadl(regs); #endif } staticinlinevoid_ohci_writel(conststructohci_hcd*ohci, constunsignedintval,__hc32__iomem*regs) { #ifdefCONFIG_USB_OHCI_BIG_ENDIAN_MMIO big_endian_mmio(ohci)? writel_be(val,regs): writel(val,regs); #else writel(val,regs); #endif } #defineohci_readl(o,r)_ohci_readl(o,r) #defineohci_writel(o,v,r)_ohci_writel(o,v,r)
h,看到这里,你应该发现大部分底层操作其实也都是ohci帮助一起完成的。每个hostdriver其实就是注册了一下,告知了mem地址在哪。下面这段代码就是ohci-s3c2410.c中probe函数的代码。
hcd->regs=devm_ioremap_resource(&dev->dev,&dev->resource[0]); if(IS_ERR(hcd->regs)){ retval=PTR_ERR(hcd->regs); gotoerr_put; }
4、usb驱动怎么学
如果从代码结构来说,上面这段分析算是入门了。但是,如果要深入了解usbhost&device驱动,那么除了这些代码逻辑,那么还要熟读usb协议手册,更重要的学会用catc协议分析仪真正地去了解usb是如何发包和收包的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。