Android/Linux USB Gadget:三层架构

1.前言

继Linux Gadget的一点研究后陆续续关注了很久Android USB Gadget,一直想写点什么记录一些认识,可是Linux USB实在是太复杂,让人有点无从下笔的感觉。它的复杂并不是说不可以被人理解,而且涉及的面很广。USB Host的驱动关注比较少,就对USB device驱动的认识来说,需从两大方面去对它进行认识和了解,一方面是USB协议本身,如果连USB端点、设备描述符、接口、复合设备等概念都不清楚的话,那是无法理解Linux USB device驱动的;另外方面就是USB Gadget架构。而本文就是基于对USB Gadget架构的一点认识而记录的。

2.Android USB 

Android设备的USB口实现了OTG的功能,也就是一般Android设备可以充当Host和Device角色,而我们使用得最多的就是它的Device角色。Android系统开发者更改传统了Linux USB Gadget实现,在传统Linux Gadget架构上实现了一个复合设备:adb和mtp。其中adb就不用多说,玩过Android都懂,mtp就是常见的U盘功能。Android USB Gadget设备驱动就是Linux的USB Gadget设备驱动。

3.USB Gadget的三层架构

一般网上关于介绍USB Gadget的资料都是基于Linux2.6.32或在这之前的版本,作者在关注了Linux2.6.37和Linux3.0.4版本的内核,USB Gadget的一些API已经与Linux2.6.32的不同了。但是那些关键的数据结构还是一样滴。
Linux USB Gadget分三层架构:
层次关系从上到下
一层:USB Gadget功能层。BSP/Driver开发者通常是要实现这一层,从而实现一个具体的设备驱动,如Anddroid在此层实现了adb,mtp,mass_storage等。浏览参考关注此层代码时,会发现“composite”是此层的关键字,此层中关键的数据结构是:struct  usb_composite_driver。这一层的驱动文件一般为:driver/usb/gadget/android.c(android实现的)或driver/usb/gadget/serial.c(传统Linux实现的USB转串口)。

二层:USB设备层。这一层是Linux内核开发维护者实现的,与我们没太大关系,不用我们操心,我们只关心其的一些接口就行。浏览参考关注此层时,会发现“gadget”是此层的关键字,此层的关键数据结构是:usb_gadget_driver,usb_composite_dev。这层主要的一个驱动文件为:driver/usb/gadget/composite.c

三层:USB设备控制器驱动层。这一层主要是与CPU、CPU USB控制器有关,与硬件紧密相关,这一层也比较头痛,主要它和USB控制器牵扯在一起,涉及有寄存器、时钟、DMA等等。但是这一层往往是由芯片厂商去实现。我们一般仅需在板级文件中处理好所需要的USB接口即可。这层的关键字就是“UDC”,主要驱动文件命名含“udc”关键字,一般与CPU或芯片厂商有关,如driver/usb/gadget/xxx_udc.c。

4.USB Gadget的三层架构的关系

可以用一句简单的话去概括三层的关系:USB Gadget功能层调用USB设备层的接口,USB设备层调用USB设备控制器驱动层的接口,然后USB设备控制器驱动层回调USB设备层,USB设备层回调USB Gadget功能层。
【强调本文只是想捋清楚层次的关系而已,对里面的一些函数,甚至USB gadget如果运作、整个驱动如何处理USB协议等等不做太多说明,后面会在其他文章中陆续补充。】

4.1从Android的gadget功能层去看三层架构的关系

浏览driver/usb/gadget/android.c源码。
先看init函数,
static int __init init(void)
{
	struct android_dev *dev;
	int err;

	android_class = class_create(THIS_MODULE, "android_usb");
	if (IS_ERR(android_class))
		return PTR_ERR(android_class);

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return -ENOMEM;

	dev->functions = supported_functions;
	INIT_LIST_HEAD(&dev->enabled_functions);
	INIT_WORK(&dev->work, android_work);
	mutex_init(&dev->mutex);

	err = android_create_device(dev);
	if (err) {
		class_destroy(android_class);
		kfree(dev);
		return err;
	}

	_android_dev = dev;

	/* Override composite driver functions */
	composite_driver.setup = android_setup;
	composite_driver.disconnect = android_disconnect;

	return usb_composite_probe(&android_usb_driver, android_bind);
}
composite_driver是定义在driver/usb/gadget/composite.c中,
static struct usb_gadget_driver composite_driver = {
	.speed		= USB_SPEED_HIGH,

	.unbind		= composite_unbind,

	.setup		= composite_setup,
	.disconnect	= composite_disconnect,

	.suspend	= composite_suspend,
	.resume		= composite_resume,

	.driver	= {
		.owner		= THIS_MODULE,
	},
};
可见它是一个全局的结构体,android.c中重新实现了它的setup和disconnect方法。然后调用函数usb_gadget_probe_driver(&android_usb_driver,android_bind);向USB设备层进行探测和注册。
【PS:2.6.32内核在init函数后面调用 usb_composite_register(&android_usb_driver)进行注册,2.6.37内核以后统一改为usb_gadget_probe_driver。】
usb_gadget_probe_driver(&composite_driver, composite_bind)函数定制在driver/usb/gadget/composite.c
extern int usb_composite_probe(struct usb_composite_driver *driver,
			       int (*bind)(struct usb_composite_dev *cdev))
{
	if (!driver || !driver->dev || !bind || composite)
		return -EINVAL;

	if (!driver->iProduct)
		driver->iProduct = driver->name;
	if (!driver->name)
		driver->name = "composite";
	composite_driver.function =  (char *) driver->name;
	composite_driver.driver.name = driver->name;
	composite = driver;
	composite_gadget_bind = bind;

	return usb_gadget_probe_driver(&composite_driver, composite_bind);
}
函数usb_gadget_probe_driver调用usb_gadget_probe_driver相关USB设备控制器驱动层进行注册。

【PS:2.6.32内核在init函数后面调用 usb_gadget_register_driver(&composite_driver)进行注册,2.6.37内核以后统一改为usb_gadget_probe_driver(&composite_driver, composite_bind);】

usb_gadget_probe_driver()函数是每一个USB设备控制器驱动要实现的,这个函数与硬件紧密相关。
至此可以看到三层的关系:USB Gadget功能层调用USB设备层的接口,USB设备层调用USB设备控制器驱动层的接口。

4.2从传统Linux的gadget功能层去看三层架构的关系

发现打字好累,分析传统Linux的gadget功能层代码(如:driver/usb/gadget/serial.c)发现其实和android一样,所以不写了。


后面会继续分析gadget层中对USB协议的实现,如怎么枚举设备,USB描述符怎么传递,数据怎么收发等。。。

你可能感兴趣的:(Linux驱动,Android系统)