16-实例_S3C6410 USB 2.0的UDC驱动
20.4.2 实例:S3C6410 USB 2.0的UDC驱动
S3C6410除了一个USB1.1主机接口以外,还包括一个USB 2.0支持OTG的控制器。它既支持主机,又支持外设功能。当使能USB_S3C_OTG_HOST选项(即“S3C USB OTG Host support”菜单时),drivers/usb/host/s3c-otg目录中的源码被选中,实现主机控制器驱动;当使能USB_GADGET_S3C_OTGD(即“S3C HS USB OTG Device”)时,drivers/usb/gadget/s3c_udc_otg.c被编译,成为一个UDC。
drivers/usb/gadget/s3c_udc.h中定义了一个s3c_udc结构体,将S3C6410 UDC的gadget、usb_gadget_driver、endpoint等封装在一起,而drivers/usb/gadget/s3c_udc_otg.c则定义了一个它的实例,如代码清单20.32所示。
代码清单20.32 S3C6410 UDC驱动的s3c_udc结构体以及实例
1 struct s3c_udc {
2 struct usb_gadget gadget;
3 struct usb_gadget_driver *driver;
4 struct platform_device *dev;
5 spinlock_t lock;
6
7 int ep0state;
8 struct s3c_ep ep[S3C_MAX_ENDPOINTS];
9
10 unsigned char usb_address;
11
12 unsigned req_pending:1, req_std:1, req_config:1;
13 };
14
15 static struct s3c_udc memory = {
16 .usb_address = 0,
17
18 .gadget = {
19 .ops = &s3c_udc_ops,
20 .ep0 = &memory.ep[0].ep,
21 .name = driver_name,
22 .dev = {
23 .bus_id = "gadget",
24 .release = nop_release,
25 },
26 },
27
28 / 控制器endpoint /
29 .ep[0] = {
30 .ep = {
31 .name = ep0name,
32 .ops = &s3c_ep_ops,
33 .maxpacket = EP0_FIFO_SIZE,
34 },
35 .dev = &memory,
36
37 .bEndpointAddress = 0,
38 .bmAttributes = 0,
39
40 .ep_type = ep_control,
41 .fifo = (unsigned int) S3C_UDC_OTG_EP0_FIFO,
42 },
43
44 / endpoints /
45 .ep[1] = {
46 .ep = {
47 .name = "ep1-bulk",
48 .ops = &s3c_ep_ops,
49 .maxpacket = EP_FIFO_SIZE,
50 },
51 .dev = &memory,
52
53 .bEndpointAddress = USB_DIR_OUT | 1,
54 .bmAttributes = USB_ENDPOINT_XFER_BULK,
55
56 .ep_type = ep_bulk_out,
57 .fifo = (unsigned int) S3C_UDC_OTG_EP1_FIFO,
58 },
59
60 .ep[2] = {
61 ...
62 .bEndpointAddress = USB_DIR_IN | 2,
63 .bmAttributes = USB_ENDPOINT_XFER_BULK,
64
65 .ep_type = ep_bulk_in,
66 },
67
68 .ep[3] = {
69 ...
70 .bEndpointAddress = USB_DIR_IN | 3,
71 .bmAttributes = USB_ENDPOINT_XFER_INT,
72 ...
73 },
74 .ep[4] = {
75 ...
76 .bEndpointAddress = USB_DIR_OUT | 4,
77 .bmAttributes = USB_ENDPOINT_XFER_BULK,
78 ...
79 },
80 .ep[5] = {
81 ...
82 .bEndpointAddress = USB_DIR_IN | 5,
83 .bmAttributes = USB_ENDPOINT_XFER_BULK,
84
85 .ep_type = ep_bulk_in,
86 },
87 .ep[6] = {
88 ...
89 .bEndpointAddress = USB_DIR_IN | 6,
90 .bmAttributes = USB_ENDPOINT_XFER_INT,
91
92 .ep_type = ep_interrupt,
93 },
94 .ep[7] = {
95 ...
96 .bEndpointAddress = USB_DIR_OUT | 7,
97 .bmAttributes = USB_ENDPOINT_XFER_BULK,
98
99 .ep_type = ep_bulk_out,
100 },
101 ...
102 };
上述代码的第18~26行是对UDC整体的描述以及操作,从第29行起,描述的就是S3C6410 UDC的各个端点的类型、地址和操作。s3c_udc类型的memory是一个全局变量,实际上,在drivers/usb/gadget/s3c_udc_otg.c是一个基于platform的设备驱动的probe()过程中,还会进一步初始化memory中的各成员,例如通过list_add_tail()将各endpoint添加到ep_list等。
drivers/usb/gadget/s3c_udc_otg.c其他主要工作是根据endpoint的列表配置硬件和完成usb_request数据发送和接收请求,实现s3c_udc_ops和s3c_ep_ops这两个结构体的成员函数,实现usb_gadget_register_driver()、usb_gadget_unregister_driver()这两个API等。