Linux USB Gadget--软件结构

USB Gadget是分层的软件结构,本文分析的是2.6.32.2版本的Gadget软件结构,这个软件结构与以前版本的变化很大。USB Gadget软件结构总共分为三层:
一. UDC层
        这一层是与硬件相关层。相关文件s3c2410_udc.c s3c2410_udc.h。s3c2410设备控制器作为一个linux设备在这一层是作为platform设备而注册到linux设备模型中的。相关数据结构以及相关函数如下:
1 数据结构
  1. struct s3c2410_udc {  
  2.     spinlock_t          lock;  
  3.   
  4.     struct s3c2410_ep       ep[S3C2410_ENDPOINTS];  
  5.     int             address;  
  6.     struct usb_gadget       gadget;  
  7.     struct usb_gadget_driver    *driver;  
  8.     struct s3c2410_request      fifo_req;  
  9.     u8              fifo_buf[EP_FIFO_SIZE];  
  10.     u16             devstatus;  
  11.   
  12.     u32             port_status;  
  13.     int             ep0state;  
  14.   
  15.     unsigned            got_irq : 1;  
  16.   
  17.     unsigned            req_std : 1;  
  18.     unsigned            req_config : 1;  
  19.     unsigned            req_pending : 1;  
  20.     u8              vbus;  
  21.     struct dentry           *regs_info;  
  22. };  
struct s3c2410_udc {
	spinlock_t			lock;

	struct s3c2410_ep		ep[S3C2410_ENDPOINTS];
	int				address;
	struct usb_gadget		gadget;
	struct usb_gadget_driver	*driver;
	struct s3c2410_request		fifo_req;
	u8				fifo_buf[EP_FIFO_SIZE];
	u16				devstatus;

	u32				port_status;
	int				ep0state;

	unsigned			got_irq : 1;

	unsigned			req_std : 1;
	unsigned			req_config : 1;
	unsigned			req_pending : 1;
	u8				vbus;
	struct dentry			*regs_info;
};
        s3c2410_udc.c中声明了一个结构体变量memory,这儿变量代表了S3C2410的USB设备控制器,包括各种信息。
  1. static struct s3c2410_udc memory = {  
  2.     .gadget = {  
  3.         .ops        = &s3c2410_ops,  
  4.         .ep0        = &memory.ep[0].ep,  
  5.         .name       = gadget_name,  
  6.         .dev = {  
  7.             .init_name  = "gadget",  
  8.         },  
  9.     },  
  10.   
  11.     /* control endpoint */  
  12.     .ep[0] = {  
  13.         .num        = 0,  
  14.         .ep = {  
  15.             .name       = ep0name,  
  16.             .ops        = &s3c2410_ep_ops,  
  17.             .maxpacket  = EP0_FIFO_SIZE,  
  18.         },  
  19.         .dev        = &memory,  
  20.     },  
  21.   
  22.     /* first group of endpoints */  
  23.     .ep[1] = {  
  24.         .num        = 1,  
  25.         .ep = {  
  26.             .name       = "ep1-bulk",  
  27.             .ops        = &s3c2410_ep_ops,  
  28.             .maxpacket  = EP_FIFO_SIZE,  
  29.         },  
  30.         .dev        = &memory,  
  31.         .fifo_size  = EP_FIFO_SIZE,  
  32.         .bEndpointAddress = 1,  
  33.         .bmAttributes   = USB_ENDPOINT_XFER_BULK,  
  34.     },  
  35.     .ep[2] = {  
  36.         .num        = 2,  
  37.         .ep = {  
  38.             .name       = "ep2-bulk",  
  39.             .ops        = &s3c2410_ep_ops,  
  40.             .maxpacket  = EP_FIFO_SIZE,  
  41.         },  
  42.         .dev        = &memory,  
  43.         .fifo_size  = EP_FIFO_SIZE,  
  44.         .bEndpointAddress = 2,  
  45.         .bmAttributes   = USB_ENDPOINT_XFER_BULK,  
  46.     },  
  47.     .ep[3] = {  
  48.         .num        = 3,  
  49.         .ep = {  
  50.             .name       = "ep3-bulk",  
  51.             .ops        = &s3c2410_ep_ops,  
  52.             .maxpacket  = EP_FIFO_SIZE,  
  53.         },  
  54.         .dev        = &memory,  
  55.         .fifo_size  = EP_FIFO_SIZE,  
  56.         .bEndpointAddress = 3,  
  57.         .bmAttributes   = USB_ENDPOINT_XFER_BULK,  
  58.     },  
  59.     .ep[4] = {  
  60.         .num        = 4,  
  61.         .ep = {  
  62.             .name       = "ep4-bulk",  
  63.             .ops        = &s3c2410_ep_ops,  
  64.             .maxpacket  = EP_FIFO_SIZE,  
  65.         },  
  66.         .dev        = &memory,  
  67.         .fifo_size  = EP_FIFO_SIZE,  
  68.         .bEndpointAddress = 4,  
  69.         .bmAttributes   = USB_ENDPOINT_XFER_BULK,  
  70.     }  
  71.   
  72. };  
static struct s3c2410_udc memory = {
	.gadget = {
		.ops		= &s3c2410_ops,
		.ep0		= &memory.ep[0].ep,
		.name		= gadget_name,
		.dev = {
			.init_name	= "gadget",
		},
	},

	/* control endpoint */
	.ep[0] = {
		.num		= 0,
		.ep = {
			.name		= ep0name,
			.ops		= &s3c2410_ep_ops,
			.maxpacket	= EP0_FIFO_SIZE,
		},
		.dev		= &memory,
	},

	/* first group of endpoints */
	.ep[1] = {
		.num		= 1,
		.ep = {
			.name		= "ep1-bulk",
			.ops		= &s3c2410_ep_ops,
			.maxpacket	= EP_FIFO_SIZE,
		},
		.dev		= &memory,
		.fifo_size	= EP_FIFO_SIZE,
		.bEndpointAddress = 1,
		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
	},
	.ep[2] = {
		.num		= 2,
		.ep = {
			.name		= "ep2-bulk",
			.ops		= &s3c2410_ep_ops,
			.maxpacket	= EP_FIFO_SIZE,
		},
		.dev		= &memory,
		.fifo_size	= EP_FIFO_SIZE,
		.bEndpointAddress = 2,
		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
	},
	.ep[3] = {
		.num		= 3,
		.ep = {
			.name		= "ep3-bulk",
			.ops		= &s3c2410_ep_ops,
			.maxpacket	= EP_FIFO_SIZE,
		},
		.dev		= &memory,
		.fifo_size	= EP_FIFO_SIZE,
		.bEndpointAddress = 3,
		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
	},
	.ep[4] = {
		.num		= 4,
		.ep = {
			.name		= "ep4-bulk",
			.ops		= &s3c2410_ep_ops,
			.maxpacket	= EP_FIFO_SIZE,
		},
		.dev		= &memory,
		.fifo_size	= EP_FIFO_SIZE,
		.bEndpointAddress = 4,
		.bmAttributes	= USB_ENDPOINT_XFER_BULK,
	}

};
2 函数
        platform设备需要注册一个platform_driver的结构体:
  1. static struct platform_driver udc_driver_2410 = {  
  2.     .driver     = {  
  3.         .name   = "s3c2410-usbgadget",  
  4.         .owner  = THIS_MODULE,  
  5.     },  
  6.     .probe      = s3c2410_udc_probe,  
  7.     .remove     = s3c2410_udc_remove,  
  8.     .suspend    = s3c2410_udc_suspend,  
  9.     .resume     = s3c2410_udc_resume,  
  10. };  
static struct platform_driver udc_driver_2410 = {
	.driver		= {
		.name	= "s3c2410-usbgadget",
		.owner	= THIS_MODULE,
	},
	.probe		= s3c2410_udc_probe,
	.remove		= s3c2410_udc_remove,
	.suspend	= s3c2410_udc_suspend,
	.resume		= s3c2410_udc_resume,
};
        结构体中的相关函数需要自己实现。最关键的函数就是s3c2410_udc_probe。这个函数在platform总线为驱动程序找到合适的设备后调用,在函数内初始化设备的时钟,申请io资源以及irq资源初始化platform设备结构体struct s3c2410_udc memory。

        以上的数据结构以及函数是UDC的硬件层,不同的UDC采取不同的策略。s3c2410是集成的USB设备控制器,所以就是采用platform驱动的形式来注册的。如果系统是外接的USB设备控制器,那么则会采用相应总线的注册形式,比如PCI等。platform驱动的唯一目的就是分配资源以及初级初始化硬件,对于USB设备层和功能驱动层都没有影响。UDC层与USB设备层是通过另外的数据结构进行交互的。这种方式就是使用两个结构体与两个函数, 两个结构体分别是struct usb_gadget与struct usb_gadget_driver,他们都是嵌入在struct s3c2410_udc结构中的,但是是由不同软件层的代码初始化的。首先看struct usb_gadget,他是在定义memory的时候就进行了初始化,是在UDC层中初始化的。而struct usb_gadget_driver是在USB设备层中初始化的,他是通过usb_gadget_register_driver(struct usb_gadget_driver *driver)函数从USB设备层传过来然后赋值给memory的。这里出现一个关键的函数usb_gadget_register_driver(struct usb_gadget_driver *driver)这个函数就是UDC层与USB设备层进行交互的函数。设备设备层通过调用它与UDC层联系在一起。这个函数将usb_gadget与usb_gadget_driver联系在一起。向USB设备层提供usb_gadget_register_driver(struct usb_gadget_driver *driver)是UDC层的基本任务,但是UDC层要做的不仅如此,UDC层还需要提供为usb_gadget服务的相关函数,这些函数会通过usb_gadget传递给USB设备层。UDC层还需要提供USB设备的中断处理程序,中断处理尤其重要。因为所有的USB传输都是由主机发起,而有没有USB传输完全由USB中断判定,所以USB中断处理程序是整个软件架构的核心。UDC层主要提供以下的函数与数据结构:

(1) usb_gadget操作函数集合 

  1. static const struct usb_gadget_ops s3c2410_ops = {  
  2.     .get_frame      = s3c2410_udc_get_frame,  
  3.     .wakeup         = s3c2410_udc_wakeup,  
  4.     .set_selfpowered    = s3c2410_udc_set_selfpowered,  
  5.     .pullup         = s3c2410_udc_pullup,  
  6.     .vbus_session       = s3c2410_udc_vbus_session,  
  7.     .vbus_draw      = s3c2410_vbus_draw,  
  8. };  
static const struct usb_gadget_ops s3c2410_ops = {
	.get_frame		= s3c2410_udc_get_frame,
	.wakeup			= s3c2410_udc_wakeup,
	.set_selfpowered	= s3c2410_udc_set_selfpowered,
	.pullup			= s3c2410_udc_pullup,
	.vbus_session		= s3c2410_udc_vbus_session,
	.vbus_draw		= s3c2410_vbus_draw,
};
        这些函数都是由UDC层来实现的。
(2) 端点操作函数集合
  1. static const struct usb_ep_ops s3c2410_ep_ops = {  
  2.     .enable     = s3c2410_udc_ep_enable,  
  3.     .disable    = s3c2410_udc_ep_disable,  
  4.   
  5.     .alloc_request  = s3c2410_udc_alloc_request,  
  6.     .free_request   = s3c2410_udc_free_request,  
  7.   
  8.     .queue      = s3c2410_udc_queue,  
  9.     .dequeue    = s3c2410_udc_dequeue,  
  10.   
  11.     .set_halt   = s3c2410_udc_set_halt,  
  12. };  
static const struct usb_ep_ops s3c2410_ep_ops = {
	.enable		= s3c2410_udc_ep_enable,
	.disable	= s3c2410_udc_ep_disable,

	.alloc_request	= s3c2410_udc_alloc_request,
	.free_request	= s3c2410_udc_free_request,

	.queue		= s3c2410_udc_queue,
	.dequeue	= s3c2410_udc_dequeue,

	.set_halt	= s3c2410_udc_set_halt,
};
(3) USB 中断处理程序
  1. static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)  
static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
(4) 其他相关辅助函数,比如调试相关函数。
二 USB设备层
        USB设备层,虽然名字上与设备相关。但是属于硬件无关层。这一层相关的代码是composite.c,composite.h。这一层的功能是隔离Gadget功能驱动与硬件相关层。使得功能驱动直接与USB设备层交互不用考虑硬件的相关细节。还有USB设备层提供了USB设备的一些基本数据结构,不同的Gadget功能驱动可以共同调用。如果没有这一层,则每一个功能驱动都需要实现自己的USB设备,导致了代码重用率很高。这一层向下与UDC层进行交互,向上与Gadget功能驱动层进行交互。在UDC层已经介绍了USB设备层向下与UDC层交互方式主要是通过调用usb_gadget_register_driver(struct usb_gadget_driver *driver),这个函数是UDC层提供的。而这个函数传递的参数就是一个usb_gadget_driver的结构体。以下是这个结构体定义:
  1. struct usb_gadget_driver {  
  2.     char            *function;  
  3.     enum usb_device_speed   speed;  
  4.     int         (*bind)(struct usb_gadget *);  
  5.     void            (*unbind)(struct usb_gadget *);  
  6.     int         (*setup)(struct usb_gadget *,  
  7.                     const struct usb_ctrlrequest *);  
  8.     void            (*disconnect)(struct usb_gadget *);  
  9.     void            (*suspend)(struct usb_gadget *);  
  10.     void            (*resume)(struct usb_gadget *);  
  11.   
  12.     /* FIXME support safe rmmod */  
  13.     struct device_driver    driver;  
  14. };  
struct usb_gadget_driver {
	char			*function;
	enum usb_device_speed	speed;
	int			(*bind)(struct usb_gadget *);
	void			(*unbind)(struct usb_gadget *);
	int			(*setup)(struct usb_gadget *,
					const struct usb_ctrlrequest *);
	void			(*disconnect)(struct usb_gadget *);
	void			(*suspend)(struct usb_gadget *);
	void			(*resume)(struct usb_gadget *);

	/* FIXME support safe rmmod */
	struct device_driver	driver;
};
        在composite.c中声明了一个这样的一个结构体变量:composite_driver,这个结构体变量就是传给usb_gadget_register_driver(struct usb_gadget_driver *driver)的参数。
  1. static struct usb_gadget_driver composite_driver = {  
  2.     .speed      = USB_SPEED_HIGH,  
  3.   
  4.     .bind       = composite_bind,  
  5.     .unbind     = __exit_p(composite_unbind),  
  6.   
  7.     .setup      = composite_setup,  
  8.     .disconnect = composite_disconnect,  
  9.   
  10.     .suspend    = composite_suspend,  
  11.     .resume     = composite_resume,  
  12.   
  13.     .driver = {  
  14.         .owner      = THIS_MODULE,  
  15.     },  
  16. };  
static struct usb_gadget_driver composite_driver = {
	.speed		= USB_SPEED_HIGH,

	.bind		= composite_bind,
	.unbind		= __exit_p(composite_unbind),

	.setup		= composite_setup,
	.disconnect	= composite_disconnect,

	.suspend	= composite_suspend,
	.resume		= composite_resume,

	.driver	= {
		.owner		= THIS_MODULE,
	},
};
        以上所有的函数集都需要自己实现,这些函数的大部分参数都是usb_gadget。可以看出这些函数都是与UDC层相关的。以上数据结构是与UDC进行交互的,下面的数据结构以及函数是USB设备层与Gadget功能驱动层进行交互的。

(1) 数据结构

  1. struct usb_composite_dev {  
  2.     struct usb_gadget       *gadget;  
  3.     struct usb_request      *req;  
  4.     unsigned            bufsiz;  
  5.   
  6.     struct usb_configuration    *config;  
  7.   
  8.     /* private: */  
  9.     /* internals */  
  10.     struct usb_device_descriptor    desc;  
  11.     struct list_head        configs;  
  12.     struct usb_composite_driver *driver;  
  13.     u8              next_string_id;  
  14.   
  15.     /* the gadget driver won't enable the data pullup 
  16.      * while the deactivation count is nonzero. 
  17.      */  
  18.     unsigned            deactivations;  
  19.   
  20.     /* protects at least deactivation count */  
  21.     spinlock_t          lock;  
  22. };  
struct usb_composite_dev {
	struct usb_gadget		*gadget;
	struct usb_request		*req;
	unsigned			bufsiz;

	struct usb_configuration	*config;

	/* private: */
	/* internals */
	struct usb_device_descriptor	desc;
	struct list_head		configs;
	struct usb_composite_driver	*driver;
	u8				next_string_id;

	/* the gadget driver won't enable the data pullup
	 * while the deactivation count is nonzero.
	 */
	unsigned			deactivations;

	/* protects at least deactivation count */
	spinlock_t			lock;
};
         这个结构代表一个USB设备。可以看出结构体中有设备描述符以及配置。还有指向usb_gadget与usb_compsite_driver的指针。说明这个结构体联系了UDC层与功能驱动层。这个结构内嵌在了usb_gadget中,是在composite_bind函数中分配与初始化的。
  1. struct usb_composite_driver {  
  2.     const char              *name;  
  3.     const struct usb_device_descriptor  *dev;  
  4.     struct usb_gadget_strings       **strings;  
  5.   
  6.     /* REVISIT:  bind() functions can be marked __init, which 
  7.      * makes trouble for section mismatch analysis.  See if 
  8.      * we can't restructure things to avoid mismatching... 
  9.      */  
  10.   
  11.     int         (*bind)(struct usb_composite_dev *);  
  12.     int         (*unbind)(struct usb_composite_dev *);  
  13.   
  14.     /* global suspend hooks */  
  15.     void            (*suspend)(struct usb_composite_dev *);  
  16.     void            (*resume)(struct usb_composite_dev *);  
  17. };  
struct usb_composite_driver {
	const char				*name;
	const struct usb_device_descriptor	*dev;
	struct usb_gadget_strings		**strings;

	/* REVISIT:  bind() functions can be marked __init, which
	 * makes trouble for section mismatch analysis.  See if
	 * we can't restructure things to avoid mismatching...
	 */

	int			(*bind)(struct usb_composite_dev *);
	int			(*unbind)(struct usb_composite_dev *);

	/* global suspend hooks */
	void			(*suspend)(struct usb_composite_dev *);
	void			(*resume)(struct usb_composite_dev *);
};
        这个结构体代表一个USB设备驱动,是联系功能驱动的主要数据结构。由功能驱动层声明并初始化。
(2) 函数
  1.  int __init usb_composite_register(struct usb_composite_driver *driver)  
  2. {  
  3.     if (!driver || !driver->dev || !driver->bind || composite)  
  4.         return -EINVAL;  
  5.   
  6.     if (!driver->name)  
  7.         driver->name = "composite";  
  8.     composite_driver.function =  (char *) driver->name;  
  9.     composite_driver.driver.name = driver->name;  
  10.     composite = driver;  
  11.   
  12.     return usb_gadget_register_driver(&composite_driver);  
  13. }  
 int __init usb_composite_register(struct usb_composite_driver *driver)
{
	if (!driver || !driver->dev || !driver->bind || composite)
		return -EINVAL;

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

	return usb_gadget_register_driver(&composite_driver);
}
        这个函数是由Gadget功能驱动层调用的,他简单初始化了composite_driver。然后调用usb_gadget_register_driver。composite是usb_composite_drver类型的全局指针这里赋值了功能驱动传递过来的driver。所以功能驱动层与USB设备层联系在了一起,usb_gadget_register_driver调用后UDC层与USB设备层联系到了一起。usb_composite_register是在功能驱动的模块初始化的函数中进行的调用。所以只要功能驱动一加载,三个软件层就通过数据结构联系在了一起。
三 Gadget 功能驱动层
        Gadget 功能驱动层是USB Gadget软件结构的最上层。主要是实现USB设备的功能,这一层通常与linux内核的其他层有密切的联系。模拟U盘的gadget就与文件系统层与块IO层有着联系。这里主要介绍最简单的Gadget 功能驱动zero。这一层包括zero.c。该驱动是作为一个模块注册到内核的,首先看一下他的模块初始化函数:
  1. static int __init init(void)  
  2. {  
  3.     return usb_composite_register(&zero_driver);  
  4. }  
static int __init init(void)
{
	return usb_composite_register(&zero_driver);
}
        非常简单,只调用了usb_composite_register,上面已经说到这个函数一旦调用三个软件层就联系到了一起。函数的参数是zero_driver。这是一个usb_composite_driver的结构体,有如下声明:
  1. static struct usb_composite_driver zero_driver = {  
  2.     .name       = "zero",  
  3.     .dev        = &device_desc,  
  4.     .strings    = dev_strings,  
  5.     .bind       = zero_bind,  
  6.     .unbind     = zero_unbind,  
  7.     .suspend    = zero_suspend,  
  8.     .resume     = zero_resume,  
  9. };  
static struct usb_composite_driver zero_driver = {
	.name		= "zero",
	.dev		= &device_desc,
	.strings	= dev_strings,
	.bind		= zero_bind,
	.unbind		= zero_unbind,
	.suspend	= zero_suspend,
	.resume		= zero_resume,
};
        zero只要实现上面的函数集合就可以了,至此Linux下USB Gadget软件结构就分析完了。这个只是三层怎样联系起来的,但是数据怎样传输的还得另行分析。主要软件结构如下图所示:

 


Linux USB Gadget软件结构这三层其中两层是与硬件无关的,分别是Gadget功能驱动层,USB设备层。一层是与硬件相关的是UDC层。每一层都提供一种关键的数据结构与函数与其他层交互。
        Gadget功能驱动层:  最主要的结构是struct usb_composite_driver,这个结构在这层定义,并且实现结构中的各个函数。
        USB设备层:  最主要的数据结构是struct usb_composite_dev与usb_gadget_driver。前一个代表一个USB设备,而后一个是Gadget驱动,与UDC层交互。
        UDC层:  最主要的数据结构是struct usb_gadget,通常包含在其他结构体中。这个结构体代表了一个USB设备控制器的所有关于USB通信的信息。
        UDC层提供usb_gadget_unregister_driver(struct usb_gadget_driver *driver)函数,这个函数由USB设备层调用,USB设备层将自己定义的struct usb_gadget_driver结构变量传递给他。USB设备层提供usb_composite_register(struct usb_composite_driver *driver)函数,这个函数由Gadget功能驱动层调用,Gadget功能驱动层将自己定义的struct usb_composite_driver 结构变量传递给他。下面详细分析一下这三层是如何结合在一起的。我们将以zero Gadget功能驱动为例子,s3c2410_udc作为底层UDC。
        首先先看一下zero Gadget功能驱动,他是作为一个模块注册到内核中的,首先分析一下他的模块初始化函数:

  1. static int __init init(void)  
  2. {  
  3.     return usb_composite_register(&zero_driver);  
  4. }  
static int __init init(void)
{
	return usb_composite_register(&zero_driver);
}

        很简单,只是调用了usb_composite_register,传递给他的参数是zero_driver。这个结构体如下定义:

  1. static struct usb_composite_driver zero_driver = {  
  2.     .name       = "zero",  
  3.     .dev        = &device_desc,  
  4.     .strings    = dev_strings,  
  5.     .bind       = zero_bind,  
  6.     .unbind     = zero_unbind,  
  7.     .suspend    = zero_suspend,  
  8.     .resume     = zero_resume,  
  9. };  
static struct usb_composite_driver zero_driver = {
	.name		= "zero",
	.dev		= &device_desc,
	.strings	= dev_strings,
	.bind		= zero_bind,
	.unbind		= zero_unbind,
	.suspend	= zero_suspend,
	.resume		= zero_resume,
};

        以上函数都是在zero.c中实现的,比较重要的函数是zero_bind。目前暂时不列出这个函数,等用到的时候再说。下面看一下usb_composite_register函数,他是由USB设备层提供的,定义在composite.c中:

  1. int __init usb_composite_register(struct usb_composite_driver *driver)  
  2. {  
  3.     if (!driver || !driver->dev || !driver->bind || composite)  
  4.         return -EINVAL;  
  5.   
  6.     if (!driver->name)  
  7.         driver->name = "composite";  
  8.     composite_driver.function =  (char *) driver->name;  
  9.     composite_driver.driver.name = driver->name;  
  10.     composite = driver;  
  11.   
  12.     return usb_gadget_register_driver(&composite_driver);  
  13. }  
int __init usb_composite_register(struct usb_composite_driver *driver)
{
	if (!driver || !driver->dev || !driver->bind || composite)
		return -EINVAL;

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

	return usb_gadget_register_driver(&composite_driver);
}

        这个函数主要的目的是初始化两个结构体变量,一个是composite_driver,这个是USB设备层定义的一个全局struct usb_gadget_driver变量,如下:

  1. static struct usb_gadget_driver composite_driver = {  
  2.     .speed      = USB_SPEED_HIGH,  
  3.   
  4.     .bind       = composite_bind,  
  5.     .unbind     = __exit_p(composite_unbind),  
  6.   
  7.     .setup      = composite_setup,  
  8.     .disconnect = composite_disconnect,  
  9.   
  10.     .suspend    = composite_suspend,  
  11.     .resume     = composite_resume,  
  12.   
  13.     .driver = {  
  14.         .owner      = THIS_MODULE,  
  15.     },  
  16. };  
static struct usb_gadget_driver composite_driver = {
	.speed		= USB_SPEED_HIGH,

	.bind		= composite_bind,
	.unbind		= __exit_p(composite_unbind),

	.setup		= composite_setup,
	.disconnect	= composite_disconnect,

	.suspend	= composite_suspend,
	.resume		= composite_resume,

	.driver	= {
		.owner		= THIS_MODULE,
	},
};

        这些函数都要在USB设备层实现。usb_composite_register将composite_driver的function初始化为"zero"。driver是 struct device_driver结构体。linux设备模型中使用。名字初始化为“zero”。另外一个变量是composite,它是一个USB设备层定义的struct usb_composite_driver的指针,这样composite就指向了zero_driver。因此zero Gadget功能驱动层就和USB设备层联系到了一起。最后usb_composite_register函数调用usb_gadget_register_driver,开始向UDC层联系。这个函数定义在UDC层,系统每个UDC都要实现这样一个函数。我们看一下s3c2410_udc这个函数的实现:

  1. int usb_gadget_register_driver(struct usb_gadget_driver *driver)  
  2. {  
  3.     struct s3c2410_udc *udc = the_controller; //the_controller指向已经初始化好了的s3c2410_udc结构,这个结构代表了s3c2410 usb设备控制器,当然他包括struct gadget结构  
  4.     int     retval;  
  5.   
  6.     dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",  
  7.         driver->driver.name);  
  8.   
  9.     /* Sanity checks */  
  10.     if (!udc)  
  11.         return -ENODEV;  
  12.   
  13.     if (udc->driver)  
  14.         return -EBUSY;  
  15.   
  16.     if (!driver->bind || !driver->setup  
  17.             || driver->speed < USB_SPEED_FULL) {  
  18.         printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",  
  19.             driver->bind, driver->setup, driver->speed);  
  20.         return -EINVAL;  
  21.     }  
  22. #if defined(MODULE)   
  23.     if (!driver->unbind) {  
  24.         printk(KERN_ERR "Invalid driver: no unbind method\n");  
  25.         return -EINVAL;  
  26.     }  
  27. #endif   
  28. /*---------------------------------------以上都是指针检查-------------------------------------------------------*/  
  29.     /* Hook the driver */  
  30.     udc->driver = driver;//传递过来的driver就是USB设备层定义的composite_driver,这样就联系了UDC层与USB设备层  
  31.     udc->gadget.dev.driver = &driver->driver; //这里赋值的driver是struct device_driver结构,供linux设备模型使用  
  32.   
  33.     /* Bind the driver */  
  34.     if ((retval = device_add(&udc->gadget.dev)) != 0) {  
  35.         printk(KERN_ERR "Error in device_add() : %d\n",retval);  
  36.         goto register_error;  
  37.     }  
  38.         //udc->gadget.dev是struct device 结构,这是向linux设备模型核心注册设备  
  39.   
  40.     dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",  
  41.         driver->driver.name);  
  42.   
  43.     if ((retval = driver->bind (&udc->gadget)) != 0) {  
  44.         device_del(&udc->gadget.dev);  
  45.         goto register_error;  
  46.     }  
  47.   
  48.     /* Enable udc */  
  49.     s3c2410_udc_enable(udc);  
  50.   
  51.     return 0;  
  52.   
  53. register_error:  
  54.     udc->driver = NULL;  
  55.     udc->gadget.dev.driver = NULL;  
  56.     return retval;  
  57. }  
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
{
	struct s3c2410_udc *udc = the_controller; //the_controller指向已经初始化好了的s3c2410_udc结构,这个结构代表了s3c2410 usb设备控制器,当然他包括struct gadget结构
	int		retval;

	dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",
		driver->driver.name);

	/* Sanity checks */
	if (!udc)
		return -ENODEV;

	if (udc->driver)
		return -EBUSY;

	if (!driver->bind || !driver->setup
			|| driver->speed < USB_SPEED_FULL) {
		printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
			driver->bind, driver->setup, driver->speed);
		return -EINVAL;
	}
#if defined(MODULE)
	if (!driver->unbind) {
		printk(KERN_ERR "Invalid driver: no unbind method\n");
		return -EINVAL;
	}
#endif
/*---------------------------------------以上都是指针检查-------------------------------------------------------*/
	/* Hook the driver */
	udc->driver = driver;//传递过来的driver就是USB设备层定义的composite_driver,这样就联系了UDC层与USB设备层
	udc->gadget.dev.driver = &driver->driver; //这里赋值的driver是struct device_driver结构,供linux设备模型使用

	/* Bind the driver */
	if ((retval = device_add(&udc->gadget.dev)) != 0) {
		printk(KERN_ERR "Error in device_add() : %d\n",retval);
		goto register_error;
	}
        //udc->gadget.dev是struct device 结构,这是向linux设备模型核心注册设备

	dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
		driver->driver.name);

	if ((retval = driver->bind (&udc->gadget)) != 0) {
		device_del(&udc->gadget.dev);
		goto register_error;
	}

	/* Enable udc */
	s3c2410_udc_enable(udc);

	return 0;

register_error:
	udc->driver = NULL;
	udc->gadget.dev.driver = NULL;
	return retval;
}

    这个函数最开始的功能是将UDC层与USB设备层联系在一起,然后调用driver->bind (&udc->gadget)函数。开始了最重要的绑定工作。只有这个函数执行完毕这三层才真正的结合在一起,USB设备正常的工作。driver就是传递过来的在USB设备层定义的composite_driver。所以driver->bind (&udc->gadget)函数是在composite.c中定义的,如下:

  1. static int __init composite_bind(struct usb_gadget *gadget)  
  2. {  
  3.     struct usb_composite_dev    *cdev;  
  4.     int             status = -ENOMEM;  
  5.   
  6.     cdev = kzalloc(sizeof *cdev, GFP_KERNEL);  //分配内存,struct usb_composite_dev结构代表了一个USB设备  
  7.     if (!cdev)  
  8.         return status;  
  9.   
  10.     spin_lock_init(&cdev->lock);  
  11.     cdev->gadget = gadget;   //这个gadget也就是s3c2410_udc.c中定义的  
  12.     set_gadget_data(gadget, cdev); //这个函数的功能就是是得gadget->dev->driver_data指向cdev结构。gadget->dev是struct device结构已经注册到了Linux设备驱动模型核心  
  13.     INIT_LIST_HEAD(&cdev->configs);  //cdev->configs是struct list_head结构指针,这个链表将链接设备的所有配置  
  14.   
  15.     /* preallocate control response and buffer */  
  16.     cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);  
  17.         //    以上函数是非常重要的,关系着USB设备枚举。现在先不分析,当分析到USB设备枚举的时候再回头分析这个函数  
  18.     if (!cdev->req)  
  19.         goto fail;  
  20.     cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);  
  21.     if (!cdev->req->buf)  
  22.         goto fail;  
  23.     cdev->req->complete = composite_setup_complete;  
  24.     gadget->ep0->driver_data = cdev;  
  25.   
  26.     cdev->bufsiz = USB_BUFSIZ;  
  27.     cdev->driver = composite; //既然struct usb_composite_dev代表一个USB设备,他的驱动当然是Gadget功能驱动,这里是composite,在前面usb_composite_register的时候赋值zero_driver  
  28.   
  29.     usb_gadget_set_selfpowered(gadget); //设置USB设备为自供电设备,因为是设备mini2440开发板已经提供电源,当然是自供电了  
  30.   
  31.     /* interface and string IDs start at zero via kzalloc. 
  32.      * we force endpoints to start unassigned; few controller 
  33.      * drivers will zero ep->driver_data. 
  34.      */  
  35.     usb_ep_autoconfig_reset(cdev->gadget);//这个函数主要的功能是遍历gadget端点链表,将端点的driver_data清空  
  36.   
  37.     /* composite gadget needs to assign strings for whole device (like 
  38.      * serial number), register function drivers, potentially update 
  39.      * power state and consumption, etc 
  40.      */  
  41.     status = composite->bind(cdev); //这个函数调用就涉及到Gadget功能驱动层了,这里也就是zero.c,composite->bind定义与zero.c中。经过这个调用三层才真正的联系在了一起。  
  42.     if (status < 0)  
  43.         goto fail;  
  44.         //以下代码都是设备描述符相关的,cdev->desc是truct usb_device_descriptor结构代表了一个USB设备描述符。这里用Gadget功能驱动层传递过来的参数初始化这个结构  
  45.     cdev->desc = *composite->dev;  
  46.     cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;  
  47.   
  48.     /* standardized runtime overrides for device ID data */  
  49.     if (idVendor)  
  50.         cdev->desc.idVendor = cpu_to_le16(idVendor);  
  51.     if (idProduct)  
  52.         cdev->desc.idProduct = cpu_to_le16(idProduct);  
  53.     if (bcdDevice)  
  54.         cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);  
  55.   
  56.     /* strings can't be assigned before bind() allocates the 
  57.      * releavnt identifiers 
  58.      */  
  59.     if (cdev->desc.iManufacturer && iManufacturer)  
  60.         string_override(composite->strings,  
  61.             cdev->desc.iManufacturer, iManufacturer);  
  62.     if (cdev->desc.iProduct && iProduct)  
  63.         string_override(composite->strings,  
  64.             cdev->desc.iProduct, iProduct);  
  65.     if (cdev->desc.iSerialNumber && iSerialNumber)  
  66.         string_override(composite->strings,  
  67.             cdev->desc.iSerialNumber, iSerialNumber);  
  68.   
  69.     INFO(cdev, "%s ready\n", composite->name);  
  70.     return 0;  
  71.   
  72. fail:  
  73.     composite_unbind(gadget);  
  74.     return status;  
  75. }  
static int __init composite_bind(struct usb_gadget *gadget)
{
	struct usb_composite_dev	*cdev;
	int				status = -ENOMEM;

	cdev = kzalloc(sizeof *cdev, GFP_KERNEL);  //分配内存,struct usb_composite_dev结构代表了一个USB设备
	if (!cdev)
		return status;

	spin_lock_init(&cdev->lock);
	cdev->gadget = gadget;   //这个gadget也就是s3c2410_udc.c中定义的
	set_gadget_data(gadget, cdev); //这个函数的功能就是是得gadget->dev->driver_data指向cdev结构。gadget->dev是struct device结构已经注册到了Linux设备驱动模型核心
	INIT_LIST_HEAD(&cdev->configs);  //cdev->configs是struct list_head结构指针,这个链表将链接设备的所有配置

	/* preallocate control response and buffer */
	cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
        //    以上函数是非常重要的,关系着USB设备枚举。现在先不分析,当分析到USB设备枚举的时候再回头分析这个函数
	if (!cdev->req)
		goto fail;
	cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
	if (!cdev->req->buf)
		goto fail;
	cdev->req->complete = composite_setup_complete;
	gadget->ep0->driver_data = cdev;

	cdev->bufsiz = USB_BUFSIZ;
	cdev->driver = composite; //既然struct usb_composite_dev代表一个USB设备,他的驱动当然是Gadget功能驱动,这里是composite,在前面usb_composite_register的时候赋值zero_driver

	usb_gadget_set_selfpowered(gadget); //设置USB设备为自供电设备,因为是设备mini2440开发板已经提供电源,当然是自供电了

	/* interface and string IDs start at zero via kzalloc.
	 * we force endpoints to start unassigned; few controller
	 * drivers will zero ep->driver_data.
	 */
	usb_ep_autoconfig_reset(cdev->gadget);//这个函数主要的功能是遍历gadget端点链表,将端点的driver_data清空

	/* composite gadget needs to assign strings for whole device (like
	 * serial number), register function drivers, potentially update
	 * power state and consumption, etc
	 */
	status = composite->bind(cdev); //这个函数调用就涉及到Gadget功能驱动层了,这里也就是zero.c,composite->bind定义与zero.c中。经过这个调用三层才真正的联系在了一起。
	if (status < 0)
		goto fail;
        //以下代码都是设备描述符相关的,cdev->desc是truct usb_device_descriptor结构代表了一个USB设备描述符。这里用Gadget功能驱动层传递过来的参数初始化这个结构
	cdev->desc = *composite->dev;
	cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;

	/* standardized runtime overrides for device ID data */
	if (idVendor)
		cdev->desc.idVendor = cpu_to_le16(idVendor);
	if (idProduct)
		cdev->desc.idProduct = cpu_to_le16(idProduct);
	if (bcdDevice)
		cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);

	/* strings can't be assigned before bind() allocates the
	 * releavnt identifiers
	 */
	if (cdev->desc.iManufacturer && iManufacturer)
		string_override(composite->strings,
			cdev->desc.iManufacturer, iManufacturer);
	if (cdev->desc.iProduct && iProduct)
		string_override(composite->strings,
			cdev->desc.iProduct, iProduct);
	if (cdev->desc.iSerialNumber && iSerialNumber)
		string_override(composite->strings,
			cdev->desc.iSerialNumber, iSerialNumber);

	INFO(cdev, "%s ready\n", composite->name);
	return 0;

fail:
	composite_unbind(gadget);
	return status;
}

        composite_bind首先定义并初始化了struct usb_composite_dev结构体,通过cdev->gadget = gadget;这条语句将设备与底层的gadget联系在一起,通过cdev->driver = composite,这条语句将设备与Gadget功能驱动联系在一起。并且给设备端点0分配了一个struct usb_request,这个结构在USB枚举将发挥重要的作用。然后调用Gadget功能驱动层的bind函数。最后初始化了USB设备描述符。这个函数最重要的一步就是调用了Gadget功能驱动层的bind函数。这样,三个软件层才真正的联系在了一起。zero Gadget功能驱动层的 bind函数定义在zero.c中,如下:

  1. static int __init zero_bind(struct usb_composite_dev *cdev)  
  2. {  
  3.     int         gcnum;  
  4.     struct usb_gadget   *gadget = cdev->gadget;  
  5.     int         id;  
  6.   
  7.     /* Allocate string descriptor numbers ... note that string 
  8.      * contents can be overridden by the composite_dev glue. 
  9.      */  
  10.     id = usb_string_id(cdev);   
  11. //这个函数的功能是如果cdev->next_string_id不大于254,将cdev->next_string_id加1,返回加1后的cdev->next_string_id。这里cdev->next_string_id为0。所以执行完这个函数id = 1;  
  12.     if (id < 0)  
  13.         return id;  
  14.     strings_dev[STRING_MANUFACTURER_IDX].id = id;  
  15.     device_desc.iManufacturer = id;  
  16. //strings_dev是zero定义的字符串描述符数组,以上语句作用是是得生产厂商的字符串描述符的id为1  
  17.     id = usb_string_id(cdev);  
  18.     if (id < 0)  
  19.         return id;  
  20.     strings_dev[STRING_PRODUCT_IDX].id = id;  
  21.     device_desc.iProduct = id;  
  22. //以上语句作用是是得产品的字符串描述符的id为2   
  23.     id = usb_string_id(cdev);  
  24.     if (id < 0)  
  25.         return id;  
  26.     strings_dev[STRING_SERIAL_IDX].id = id;  
  27.     device_desc.iSerialNumber = id;  
  28. //以上语句作用是是得生产串号的字符串描述符的id为3   
  29.     setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);  
  30. //电源管理相关代码,暂时不用看   
  31.     /* Register primary, then secondary configuration.  Note that 
  32.      * SH3 only allows one config... 
  33.      */  
  34.     if (loopdefault) {  
  35.         loopback_add(cdev, autoresume != 0);  
  36.         if (!gadget_is_sh(gadget))  
  37.             sourcesink_add(cdev, autoresume != 0);  
  38.     } else {  
  39.         sourcesink_add(cdev, autoresume != 0);  
  40.         if (!gadget_is_sh(gadget))  
  41.             loopback_add(cdev, autoresume != 0);  
  42.     }  
  43. //以上代码尤其重要,是设置zero设备配置描述符的。这里不得不说一下zero驱动的功能,他有两种配置。一个是将主机发送给他的内容返回给主机,另外一个就是可以单独发送与接受数据。loopdefault是模块参数,默认值为0  
  44. //所以我们先看else后面的代码,这段代码设置的就是单独发送接受功能。gadget_is_sh是判断usb设备控制器是否支持复合设备,s3c2410不支持。所以现在只需要分析sourcesink_add(cdev, autoresume != 0)  
  45. //这个函数就可以了,见下面sourcesink_add(cdev, autoresume != 0)函数分析。  
  46.     gcnum = usb_gadget_controller_number(gadget);  
  47.     if (gcnum >= 0)  
  48.         device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);  
  49.     else {  
  50.         /* gadget zero is so simple (for now, no altsettings) that 
  51.          * it SHOULD NOT have problems with bulk-capable hardware. 
  52.          * so just warn about unrcognized controllers -- don't panic. 
  53.          * 
  54.          * things like configuration and altsetting numbering 
  55.          * can need hardware-specific attention though. 
  56.          */  
  57.         pr_warning("%s: controller '%s' not recognized\n",  
  58.             longname, gadget->name);  
  59.         device_desc.bcdDevice = cpu_to_le16(0x9999);  
  60.     }  
  61.   
  62.   
  63.     INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);  
  64.   
  65.     snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",  
  66.         init_utsname()->sysname, init_utsname()->release,  
  67.         gadget->name);  
  68.   
  69.     return 0;  
  70. }  
static int __init zero_bind(struct usb_composite_dev *cdev)
{
	int			gcnum;
	struct usb_gadget	*gadget = cdev->gadget;
	int			id;

	/* Allocate string descriptor numbers ... note that string
	 * contents can be overridden by the composite_dev glue.
	 */
	id = usb_string_id(cdev); 
//这个函数的功能是如果cdev->next_string_id不大于254,将cdev->next_string_id加1,返回加1后的cdev->next_string_id。这里cdev->next_string_id为0。所以执行完这个函数id = 1;
	if (id < 0)
		return id;
	strings_dev[STRING_MANUFACTURER_IDX].id = id;
	device_desc.iManufacturer = id;
//strings_dev是zero定义的字符串描述符数组,以上语句作用是是得生产厂商的字符串描述符的id为1
	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dev[STRING_PRODUCT_IDX].id = id;
	device_desc.iProduct = id;
//以上语句作用是是得产品的字符串描述符的id为2
	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dev[STRING_SERIAL_IDX].id = id;
	device_desc.iSerialNumber = id;
//以上语句作用是是得生产串号的字符串描述符的id为3
	setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
//电源管理相关代码,暂时不用看
	/* Register primary, then secondary configuration.  Note that
	 * SH3 only allows one config...
	 */
	if (loopdefault) {
		loopback_add(cdev, autoresume != 0);
		if (!gadget_is_sh(gadget))
			sourcesink_add(cdev, autoresume != 0);
	} else {
		sourcesink_add(cdev, autoresume != 0);
		if (!gadget_is_sh(gadget))
			loopback_add(cdev, autoresume != 0);
	}
//以上代码尤其重要,是设置zero设备配置描述符的。这里不得不说一下zero驱动的功能,他有两种配置。一个是将主机发送给他的内容返回给主机,另外一个就是可以单独发送与接受数据。loopdefault是模块参数,默认值为0
//所以我们先看else后面的代码,这段代码设置的就是单独发送接受功能。gadget_is_sh是判断usb设备控制器是否支持复合设备,s3c2410不支持。所以现在只需要分析sourcesink_add(cdev, autoresume != 0)
//这个函数就可以了,见下面sourcesink_add(cdev, autoresume != 0)函数分析。
	gcnum = usb_gadget_controller_number(gadget);
	if (gcnum >= 0)
		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
	else {
		/* gadget zero is so simple (for now, no altsettings) that
		 * it SHOULD NOT have problems with bulk-capable hardware.
		 * so just warn about unrcognized controllers -- don't panic.
		 *
		 * things like configuration and altsetting numbering
		 * can need hardware-specific attention though.
		 */
		pr_warning("%s: controller '%s' not recognized\n",
			longname, gadget->name);
		device_desc.bcdDevice = cpu_to_le16(0x9999);
	}


	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);

	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
		init_utsname()->sysname, init_utsname()->release,
		gadget->name);

	return 0;
}

        zero_bind函数首先就是设置了几个字符串描述符的id,然后就设置USB配置。主要调用了sourcesink_add函数,传递给的参数是cdev,就是USB设备层定义的USB设备结构体。这个函数定义在f_sourcesink.c,这个文件以头文件的形式包含在zero.c中。如下所示:

  1. int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume)  
  2. {  
  3.     int id;  
  4.   
  5.     /* allocate string ID(s) */  
  6.     id = usb_string_id(cdev);  
  7.     if (id < 0)  
  8.         return id;  
  9.     strings_sourcesink[0].id = id;  
  10.         //以上初始化一下字符串描述符的id   
  11.     source_sink_intf.iInterface = id;  
  12.     sourcesink_driver.iConfiguration = id;  
  13.         //source_sink_intf是struct usb_interface_descriptor类型的变量,代表一个接口  
  14.         //sourcesink_driver是struct usb_configuration类型的变量,代表一个USB配置,注意不是配置描述符。这两个变量在f_sourcesink.c中定义  
  15.     /* support autoresume for remote wakeup testing */  
  16.     if (autoresume)  
  17.         sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;  
  18.   
  19.     /* support OTG systems */  
  20.     if (gadget_is_otg(cdev->gadget)) {  
  21.         sourcesink_driver.descriptors = otg_desc;  
  22.         sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;  
  23.     }  
  24.   
  25.     return usb_add_config(cdev, &sourcesink_driver);  
  26. }  
  27.     在分析这个函数之前首先先看一下f_sourcesink.c中关键的一个数据结构,sourcesink_driver。他代表了一个USB配置,里面说明了配置的功能。如下:  
  28. static struct usb_configuration sourcesink_driver = {  
  29.     .label      = "source/sink",  
  30.     .strings    = sourcesink_strings,  
  31.     .bind       = sourcesink_bind_config,  
  32.     .setup      = sourcesink_setup,  
  33.     .bConfigurationValue = 3,  
  34.     .bmAttributes   = USB_CONFIG_ATT_SELFPOWER,  
  35.     /* .iConfiguration = DYNAMIC */  
  36. };  
int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume)
{
	int id;

	/* allocate string ID(s) */
	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_sourcesink[0].id = id;
        //以上初始化一下字符串描述符的id
	source_sink_intf.iInterface = id;
	sourcesink_driver.iConfiguration = id;
        //source_sink_intf是struct usb_interface_descriptor类型的变量,代表一个接口
        //sourcesink_driver是struct usb_configuration类型的变量,代表一个USB配置,注意不是配置描述符。这两个变量在f_sourcesink.c中定义
	/* support autoresume for remote wakeup testing */
	if (autoresume)
		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;

	/* support OTG systems */
	if (gadget_is_otg(cdev->gadget)) {
		sourcesink_driver.descriptors = otg_desc;
		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	return usb_add_config(cdev, &sourcesink_driver);
}
    在分析这个函数之前首先先看一下f_sourcesink.c中关键的一个数据结构,sourcesink_driver。他代表了一个USB配置,里面说明了配置的功能。如下:
static struct usb_configuration sourcesink_driver = {
	.label		= "source/sink",
	.strings	= sourcesink_strings,
	.bind		= sourcesink_bind_config,
	.setup		= sourcesink_setup,
	.bConfigurationValue = 3,
	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
	/* .iConfiguration = DYNAMIC */
};

        看完了这个数据结构,我们分析一下sourcesink_add最后调用的函数usb_add_config(cdev, &sourcesink_driver),这个函数传递的参数一个是USB设备一个是USB配置。显然功能是给USB设备增加一个配置。函数定义在composite.c中,如下:

  1. int __init usb_add_config(struct usb_composite_dev *cdev,  
  2.         struct usb_configuration *config)  
  3. {  
  4.     int             status = -EINVAL;  
  5.     struct usb_configuration    *c;  
  6.   
  7.     DBG(cdev, "adding config #%u '%s'/%p\n",  
  8.             config->bConfigurationValue,  
  9.             config->label, config);  
  10.   
  11.     if (!config->bConfigurationValue || !config->bind)  
  12.         goto done;  
  13.   
  14.     /* Prevent duplicate configuration identifiers */  
  15.     list_for_each_entry(c, &cdev->configs, list) {  
  16.         if (c->bConfigurationValue == config->bConfigurationValue) {  
  17.             status = -EBUSY;  
  18.             goto done;  
  19.         }  
  20.     }  
  21. /*---------------------------------------------以上都是检查参数的合法性------------------------------------------*/  
  22.     config->cdev = cdev;  
  23.     list_add_tail(&config->list, &cdev->configs);  
  24.         //一个USB设备可以有多种配置,这句是将配置加入到设备的配置链表中  
  25.   
  26.     INIT_LIST_HEAD(&config->functions);  
  27.         //初始化配置的functions链表,functions链表要链接struct usb_function类型的数据结构,这个数据结构也很重要,其实他代表一个USB接口  
  28.     config->next_interface_id = 0;  
  29.   
  30.     status = config->bind(config);  
  31.         //这里函数调用的是sourcesink_bind_config,这个函数的功能就是初始化一个struct usb_function结构,并且将其加入到配置的functions链表,见下面分析  
  32.     if (status < 0) { //status小于0说明上边函数调用失败所以删除配置  
  33.         list_del(&config->list);  
  34.         config->cdev = NULL;  
  35.     } else {  //给配置增加接口成功  
  36.         unsigned    i;  
  37.                 //打印调试信息   
  38.         DBG(cdev, "cfg %d/%p speeds:%s%s\n",  
  39.             config->bConfigurationValue, config,  
  40.             config->highspeed ? " high" : "",  
  41.             config->fullspeed  
  42.                 ? (gadget_is_dualspeed(cdev->gadget)  
  43.                     ? " full"  
  44.                     : " full/low")  
  45.                 : "");  
  46.                 //MAX_CONFIG_INTERFACES 最大接口数,定义在composite.h中,为16。每个配置可以有16个接口,一下代码遍历这个配置的所有接口,打印调试信息  
  47.         for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {  
  48.             struct usb_function *f = config->interface[i];  
  49.   
  50.             if (!f)  
  51.                 continue;  
  52.             DBG(cdev, "  interface %d = %s/%p\n",  
  53.                 i, f->name, f);  
  54.         }  
  55.     }  
  56.   
  57.     /* set_alt(), or next config->bind(), sets up 
  58.      * ep->driver_data as needed. 
  59.      */  
  60.     usb_ep_autoconfig_reset(cdev->gadget);  
  61.         //这个函数的主要作用就是将cdev->gadget的所有端点的driver_data清空  
  62. done:  
  63.     if (status)  
  64.         DBG(cdev, "added config '%s'/%u --> %d\n", config->label,  
  65.                 config->bConfigurationValue, status);  
  66.     return status;  
  67. }  
int __init usb_add_config(struct usb_composite_dev *cdev,
		struct usb_configuration *config)
{
	int				status = -EINVAL;
	struct usb_configuration	*c;

	DBG(cdev, "adding config #%u '%s'/%p\n",
			config->bConfigurationValue,
			config->label, config);

	if (!config->bConfigurationValue || !config->bind)
		goto done;

	/* Prevent duplicate configuration identifiers */
	list_for_each_entry(c, &cdev->configs, list) {
		if (c->bConfigurationValue == config->bConfigurationValue) {
			status = -EBUSY;
			goto done;
		}
	}
/*---------------------------------------------以上都是检查参数的合法性------------------------------------------*/
	config->cdev = cdev;
	list_add_tail(&config->list, &cdev->configs);
        //一个USB设备可以有多种配置,这句是将配置加入到设备的配置链表中

	INIT_LIST_HEAD(&config->functions);
        //初始化配置的functions链表,functions链表要链接struct usb_function类型的数据结构,这个数据结构也很重要,其实他代表一个USB接口
	config->next_interface_id = 0;

	status = config->bind(config);
        //这里函数调用的是sourcesink_bind_config,这个函数的功能就是初始化一个struct usb_function结构,并且将其加入到配置的functions链表,见下面分析
	if (status < 0) { //status小于0说明上边函数调用失败所以删除配置
		list_del(&config->list);
		config->cdev = NULL;
	} else {  //给配置增加接口成功
		unsigned	i;
                //打印调试信息
		DBG(cdev, "cfg %d/%p speeds:%s%s\n",
			config->bConfigurationValue, config,
			config->highspeed ? " high" : "",
			config->fullspeed
				? (gadget_is_dualspeed(cdev->gadget)
					? " full"
					: " full/low")
				: "");
                //MAX_CONFIG_INTERFACES 最大接口数,定义在composite.h中,为16。每个配置可以有16个接口,一下代码遍历这个配置的所有接口,打印调试信息
		for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {
			struct usb_function	*f = config->interface[i];

			if (!f)
				continue;
			DBG(cdev, "  interface %d = %s/%p\n",
				i, f->name, f);
		}
	}

	/* set_alt(), or next config->bind(), sets up
	 * ep->driver_data as needed.
	 */
	usb_ep_autoconfig_reset(cdev->gadget);
        //这个函数的主要作用就是将cdev->gadget的所有端点的driver_data清空
done:
	if (status)
		DBG(cdev, "added config '%s'/%u --> %d\n", config->label,
				config->bConfigurationValue, status);
	return status;
}

        这个函数初始化了配置,将配置与设备联系在一起,并且打印一些调试信息。这样设备有了配置,但是我们知道一个USB设备的配置下是接口的集合。所以函数调用config->bind(config)给配置添加接口。这个函数如下:

  1. static int __init sourcesink_bind_config(struct usb_configuration *c)  
  2. {  
  3.     struct f_sourcesink *ss;  
  4.     int         status;  
  5.   
  6.     ss = kzalloc(sizeof *ss, GFP_KERNEL);  
  7.     if (!ss)  
  8.         return -ENOMEM;  
  9.   
  10.     ss->function.name = "source/sink";  
  11.     ss->function.descriptors = fs_source_sink_descs;  
  12.     ss->function.bind = sourcesink_bind;  
  13.     ss->function.unbind = sourcesink_unbind;  
  14.     ss->function.set_alt = sourcesink_set_alt;  
  15.     ss->function.disable = sourcesink_disable;  
  16.   
  17.     status = usb_add_function(c, &ss->function);  
  18.     if (status)  
  19.         kfree(ss);  
  20.     return status;  
  21. }  
static int __init sourcesink_bind_config(struct usb_configuration *c)
{
	struct f_sourcesink	*ss;
	int			status;

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

	ss->function.name = "source/sink";
	ss->function.descriptors = fs_source_sink_descs;
	ss->function.bind = sourcesink_bind;
	ss->function.unbind = sourcesink_unbind;
	ss->function.set_alt = sourcesink_set_alt;
	ss->function.disable = sourcesink_disable;

	status = usb_add_function(c, &ss->function);
	if (status)
		kfree(ss);
	return status;
}

        可以看出这个函数分配并初始化了一个struct f_sourcesink结构体,这个结构体包含代表接口的struct usb_function。并且初始化了struct usb_function的一下回调函数。最后调用usb_add_function(c, &ss->function);将接口添加到配置中。usb_add_function函数如下所示:

  1. int __init usb_add_function(struct usb_configuration *config,  
  2.         struct usb_function *function)  
  3. {  
  4.     int value = -EINVAL;  
  5.         //打印调试信息   
  6.     DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",  
  7.             function->name, function,  
  8.             config->label, config);  
  9.        //检查参数合法性   
  10.     if (!function->set_alt || !function->disable)  
  11.         goto done;  
  12.         //添加接口到配置   
  13.     function->config = config;  
  14.     list_add_tail(&function->list, &config->functions);  
  15.           
  16.     /* REVISIT *require* function->bind? */  
  17.     if (function->bind) { //如果function定义了bind函数则调用他,这里function定义了bind函数,sourcesink_bind。这个函数进行一些初始化的工作  
  18.         value = function->bind(config, function);  
  19.         if (value < 0) {  
  20.             list_del(&function->list);  
  21.             function->config = NULL;  
  22.         }  
  23.     } else  
  24.         value = 0;  
  25.   
  26.     /* We allow configurations that don't work at both speeds. 
  27.      * If we run into a lowspeed Linux system, treat it the same 
  28.      * as full speed ... it's the function drivers that will need 
  29.      * to avoid bulk and ISO transfers. 
  30.      */  
  31.     if (!config->fullspeed && function->descriptors)  
  32.         config->fullspeed = true;  
  33.     if (!config->highspeed && function->hs_descriptors)  
  34.         config->highspeed = true;  
  35.   
  36. done:  
  37.     if (value)  
  38.         DBG(config->cdev, "adding '%s'/%p --> %d\n",  
  39.                 function->name, function, value);  
  40.     return value;  
  41. }  
int __init usb_add_function(struct usb_configuration *config,
		struct usb_function *function)
{
	int	value = -EINVAL;
        //打印调试信息
	DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",
			function->name, function,
			config->label, config);
       //检查参数合法性
	if (!function->set_alt || !function->disable)
		goto done;
        //添加接口到配置
	function->config = config;
	list_add_tail(&function->list, &config->functions);
        
	/* REVISIT *require* function->bind? */
	if (function->bind) { //如果function定义了bind函数则调用他,这里function定义了bind函数,sourcesink_bind。这个函数进行一些初始化的工作
		value = function->bind(config, function);
		if (value < 0) {
			list_del(&function->list);
			function->config = NULL;
		}
	} else
		value = 0;

	/* We allow configurations that don't work at both speeds.
	 * If we run into a lowspeed Linux system, treat it the same
	 * as full speed ... it's the function drivers that will need
	 * to avoid bulk and ISO transfers.
	 */
	if (!config->fullspeed && function->descriptors)
		config->fullspeed = true;
	if (!config->highspeed && function->hs_descriptors)
		config->highspeed = true;

done:
	if (value)
		DBG(config->cdev, "adding '%s'/%p --> %d\n",
				function->name, function, value);
	return value;
}

        我们可以看到这个函数最主要的就是联系接口与配置。并且调用接口的bind函数,zero sourcesink配置的接口的bind为sourcesink_bind。如下定义:

  1. static int __init  
  2. sourcesink_bind(struct usb_configuration *c, struct usb_function *f)  
  3. {  
  4.     struct usb_composite_dev *cdev = c->cdev;  
  5.     struct f_sourcesink *ss = func_to_ss(f);  
  6.     int id;  
  7.   
  8.     /* allocate interface ID(s) */  
  9.     id = usb_interface_id(c, f);  
  10.     if (id < 0)  
  11.         return id;  
  12.     source_sink_intf.bInterfaceNumber = id;  
  13.         //usb_interface_id(c, f)实现的功能是判断config->next_interface_id是否大于16如果不是,那么执行config->interface[id] = f,在将config->next_interface_id加1返回  
  14.     /* allocate endpoints */  
  15.         //下面是分配端点,我们知道根据USB协议。USB设备下来是USB配置,然后是USB接口,接口是USB端点的组合,根据zero sourcesink实现的功能,接口需要连个批量端点,一个In端点一个out端点  
  16.     ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);  
  17.     if (!ss->in_ep) {  
  18. autoconf_fail:  
  19.         ERROR(cdev, "%s: can't autoconfigure on %s\n",  
  20.             f->name, cdev->gadget->name);  
  21.         return -ENODEV;  
  22.     }  
  23.     ss->in_ep->driver_data = cdev;    /* claim */  
  24.   
  25.     ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);  
  26.     if (!ss->out_ep)  
  27.         goto autoconf_fail;  
  28.     ss->out_ep->driver_data = cdev;   /* claim */  
  29.   
  30.     /* support high speed hardware */  
  31.     if (gadget_is_dualspeed(c->cdev->gadget)) {  
  32.         hs_source_desc.bEndpointAddress =  
  33.                 fs_source_desc.bEndpointAddress;  
  34.         hs_sink_desc.bEndpointAddress =  
  35.                 fs_sink_desc.bEndpointAddress;  
  36.         f->hs_descriptors = hs_source_sink_descs;  
  37.     }  
  38.   
  39.     DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",  
  40.             gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",  
  41.             f->name, ss->in_ep->name, ss->out_ep->name);  
  42.     return 0;  
  43. }  
static int __init
sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
{
	struct usb_composite_dev *cdev = c->cdev;
	struct f_sourcesink	*ss = func_to_ss(f);
	int	id;

	/* allocate interface ID(s) */
	id = usb_interface_id(c, f);
	if (id < 0)
		return id;
	source_sink_intf.bInterfaceNumber = id;
        //usb_interface_id(c, f)实现的功能是判断config->next_interface_id是否大于16如果不是,那么执行config->interface[id] = f,在将config->next_interface_id加1返回
	/* allocate endpoints */
        //下面是分配端点,我们知道根据USB协议。USB设备下来是USB配置,然后是USB接口,接口是USB端点的组合,根据zero sourcesink实现的功能,接口需要连个批量端点,一个In端点一个out端点
	ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
	if (!ss->in_ep) {
autoconf_fail:
		ERROR(cdev, "%s: can't autoconfigure on %s\n",
			f->name, cdev->gadget->name);
		return -ENODEV;
	}
	ss->in_ep->driver_data = cdev;	/* claim */

	ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
	if (!ss->out_ep)
		goto autoconf_fail;
	ss->out_ep->driver_data = cdev;	/* claim */

	/* support high speed hardware */
	if (gadget_is_dualspeed(c->cdev->gadget)) {
		hs_source_desc.bEndpointAddress =
				fs_source_desc.bEndpointAddress;
		hs_sink_desc.bEndpointAddress =
				fs_sink_desc.bEndpointAddress;
		f->hs_descriptors = hs_source_sink_descs;
	}

	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
			f->name, ss->in_ep->name, ss->out_ep->name);
	return 0;
}

        这个函数除了初始化接口的接口id。另外就是给接口分配端点了。这也是各层整合的最后一步了。zero sourcesink有一个配置,一个接口。这个接口有两个端点,一个in端点一个Out端点。usb_ep_autoconfig 函数就担当了分配端点的任务,他定义在epautoconf.c中,这个文件以头文件的形式包含在了zero.c中。这个函数有两个参数一个是struct usb_gadget类型的指针,一个是struct usb_endpoint_descriptor类型的指针,也就是端点描述符,这个函数根据端点描述符的信息,自动在struct usb_gadget里找到合适的端点。
        经过上面的重重函数调用,现在设备终于饱满了,既有配置了,也有接口了,接口里也有相应的端点了。各层的关系也都联系起来了。但是还是有一点就是感觉有点晕。确实这么多的函数调用,不晕都没办法呀。没关系,我们来重新梳理一下各个函数之间的调用关系以及各环节整合的过程。这个整合的过程大体分为两个过程:
(1) 过程方向 Gadget功能驱动层-->USB设备层-->UDC层。
         以四个数据结构为基础:struct usb_composite_driver struct usb_composite_dev struct usb_gadget_driver struct usb_gadget 
         两个register函数为导向: usb_composite_register(&zero_driver) usb_gadget_register_driver(&composite_driver)
(2) 过程方向 UDC层-->USB设备层-->Gadget功能驱动层
         四个bind函数为串联点,带出一连串数据结构与初始化。这四个bind函数分配是:
         USB设备层的composite_bind 由UDC层的usb_gadget_register_driver函数调用。功能是分配struct usb_composite_dev cdev 并初始化。struct usb_composite_dev结构串联了UDC层的usb_gadget与Gadget功能驱动层的usb_composite_driver。并且调用下一个上层的bind
         Gadget功能驱动层的zero_bind 这个函数主要的任务就是用Gadget功能驱动层的USB设备信息去进一步初始化struct usb_composite_dev结构。并且引出下面两个bind函数。
         另外两个bind函数都是与USB设备信息相关,一个是添加配置时调用的,一个是添加接口的时候调用的。这两个函数由sourcesink_add引出。 usb_add_config将配置添加到设备中引出config->bind:sourcesink_bind_config.这个bind分配并初始化接口,调用usb_add_function将接口添加到配置到,usb_add_function引出function->bind:sourcesink_bind 根据功能,在gadget里查找合适的端点。并进一步初始化struct usb_composite_dev。我们发现这些bind就是一个目的,初始化struct usb_composite_dev结构,使其逐渐丰满。因为这个结构代表一个USB设备。经过合适的初始化后设备才能正确的工作。经过重重初始化,三层总算整合在了一起了。这三层最终形成了一个饱满的struct usb_composite_dev结构。这个结构包含USB设备运行各种信息。包括:配置,接口,端点等。我们再来看一下这个结构:

  1. struct usb_composite_dev {  
  2.     struct usb_gadget       *gadget; //联系底层的UDC中的usb_gadget  
  3.     struct usb_request      *req;    //端点0的传输结构,在设备枚举的时候使用  
  4.     unsigned            bufsiz;  
  5.   
  6.     struct usb_configuration    *config; //USB配置  
  7.   
  8.     /* private: */  
  9.     /* internals */  
  10.     struct usb_device_descriptor    desc;   //设备描述符  
  11.     struct list_head        configs; //USB配置链表  
  12.     struct usb_composite_driver *driver;  //联系上层的Gadget功能驱动层  
  13.     u8              next_string_id;  
  14.   
  15.     /* the gadget driver won't enable the data pullup 
  16.      * while the deactivation count is nonzero. 
  17.      */  
  18.     unsigned            deactivations;  
  19.   
  20.     /* protects at least deactivation count */  
  21.     spinlock_t          lock;  
  22. };  
struct usb_composite_dev {
	struct usb_gadget		*gadget; //联系底层的UDC中的usb_gadget
	struct usb_request		*req;    //端点0的传输结构,在设备枚举的时候使用
	unsigned			bufsiz;

	struct usb_configuration	*config; //USB配置

	/* private: */
	/* internals */
	struct usb_device_descriptor	desc;   //设备描述符
	struct list_head		configs; //USB配置链表
	struct usb_composite_driver	*driver;  //联系上层的Gadget功能驱动层
	u8				next_string_id;

	/* the gadget driver won't enable the data pullup
	 * while the deactivation count is nonzero.
	 */
	unsigned			deactivations;

	/* protects at least deactivation count */
	spinlock_t			lock;
};

        经过初始化设备已经准备好了,将mini2440插入USB主机,就开始了设备枚举.这就涉及到了主机与设备的通信。以后再分析USB设备枚举与数据传输过程。Linux USB Gadget虽然有三层软件结构。但是只有UDC层与Gadget功能驱动层作为模块注册到内核。只有USB设备层有关的文件composite.c是以头文件的形式包含在各种Gadget功能驱动里的。以前的内核代码没有USB设备层的。所有的Gadget功能驱动都必须自己处理USB设备相关的细节,代码重复率较高,所以才出现这个USB设备层以以增加代码的重用性。composite字面上是复用的意思,不知道是不是为了原因而命名的。

原文:http://blog.csdn.net/yaozhenguo2006/article/details/7690707

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值