Linux-USB Gadget : Part 4: 最简单的 gadget驱动:g_zero
作者: zjujoe 转载请注明出处
Email : zjujoe@yahoo.com
BLOG : http://blog.csdn.net/zjujoe
前言
前面讲过, gadget api 提供了 usb device controller 驱动和上层 gadget 驱动交互的接口。 UDC 驱动是服务提供者,而各种 gadget 驱动则是服务的使用者。其实还有一些通用代码,因为功能比较简单,我们称之为 helpe 函数。在阅读了 Gadget API 文档后,让我们开始阅读代码, udb 驱动代码比较复杂,我们先从 gadget 驱动看起。各种 gadget 驱动中, 最简单的要数 g_zero 驱动。
g_zero 驱动简介
作为最简单的 gadget 驱动, g_zero 的功能基于两个 BULK 端点实现了简单的输入输出功能, 它可以用作写新的 gadget 驱动的一个实例。 g_zero 驱动还有一个重要角色, 即配合 host 端的 usbtest (内核模块及用户层代码), 用于测试底层 udc 驱动。当然,也可以是测试主机的控制器驱动。
两个 BULK 端点为一个 IN 端点 , 一个 OUT 端点。基于这两个(由底层提供的)端点, g_zero 驱动实现了两个 configuration 。 第一个 configuration 提供了 sink/source 功能:两个端点一个负责输入,一个负责输出,其中输出的内容根据设置可以是全 0 ,也可以是按照某种算法生成的数据。另一个configuration 提供了 loopback 接口, IN 端点负责把从 OUT 端点收到的数据反馈给 Host.
根据系统配置, g_zero 驱动提供了全速及高速功能,从而稍微增加了代码复杂度。另外,它还支持 otg 接口,从 usb2.0 协议我们知道, otg 其实是 usb device 实现的一个补充功能。它增加了一套接口,使得同一设备可以在设备角色以及有限主机角色之切换。上层 gadget 驱动主要是在描述符方面提供配合支持。下面我们开始看代码。
模块初始化
1309 static int __init init (void)
1310 {
1311 /* a real value would likely come through some id prom
1312 * or module option. this one takes at least two packets.
1313 */
1314 strlcpy (serial , "0123456789.0123456789.0123456789" , sizeof serial );
1315
1316 return usb_gadget_register_driver (&zero_driver );
1317 }
1318 module_init (init );
1320 static void __exit cleanup (void)
1321 {
1322 (&zero_driver );
1323 }
1324 module_exit (cleanup ); usb_gadget_unregister_driver
Serial 变量存储的是设备序列号,我们是一个非正式设备,随便填充一下。模块初始化函数调用 usb_gadget_register_driver 来向 udc driver 注册一个 gadget 驱动, 我们这里是 zero_driver 。而退出函数则会做相反的操作:调用 usb_gadget_unregister_driver 取消原来的注册。像所有的模块初始化、退出函数一样,现在还看不出什么花头。我们再看一下 zero_driver 的定义:
1283 static struct usb_gadget_driver zero_driver = {
1284 #ifdef CONFIG_USB_GADGET_DUALSPEED
1285 .speed = USB_SPEED_HIGH,
1286 #else
1287 .speed = USB_SPEED_FULL,
1288 #endif
1289 .function = (char *) longname ,
1290 .bind = zero_bind ,
1291 .unbind = __exit_p (zero_unbind ),
1293 .setup = zero_setup ,
1294 .disconnect = zero_disconnect ,
1296 .suspend = zero_suspend ,
1297 .resume = zero_resume ,
1299 .driver = {
1300 .name = (char *) shortname ,
1301 .owner = THIS_MODULE ,
1302 },
1303 };
根据 CONFIG_USB_GADGET_DUALSPEED ,代码选择是支持高速还是全速,我们使用的 PXA 平台支持高速传输,所以我们假定该配置变量为真。根据 Gadget API 文档(以及下面的代码调用图),在初始化阶段 usb_gadget_register_driver 函数会调用 bind 函数,而 setup 函数是用于处理 udc 驱动没有处理的控制传输部分。这两个函数是整个 zero gadget驱动的精华部分。其它函数则只是为了完整性而提供,有兴趣者可以对照 Gadget API 文档及代码,自行研究。至于 .driver 成员变量,那主要是为 LDM(linux device module) 服务的。现在关于 LDM 的文档满天飞,这里就不多说了。
简单起见,我们目前不去深究 udc 驱动代码(那比我们的 g_zero 驱动要复杂很多, 而且很多代码硬件相关,需要阅读硬件 spec 才能理解),而是使用 kft 及 graphviz (见参考, colorant 大侠提供的文档)工具得到函数调用关系图:(我们这里使用 pxa udc 驱动,如果使用 dummy_hcd 会得到类似但更简单的关系图)
从上图中,我们可以看到在初始化阶段, udc 驱动会调用 zero 驱动的 bind 函数,也会调用 zero 驱动的 setup 函数 ( 主要是得到一些描述符 ) , setup 函数主要是在后面我们的 device 和主机连接后用于处理控制传输的响应(大部分)。在初始阶段只是顺便帮忙提供点信息,进行的是假传输,真提供信息给 udc 驱动。下面我们重点分析 bind 函数。
函数 zero_bind
1140 static int __init
1141 zero_bind (struct usb_gadget *gadget)
1142 {
1143 struct zero_dev *dev ;
1144 struct usb_ep *ep;
1145 int gcnum;
首先映入眼帘的是 zero_bind 函数的参数,根据 Gadget API ,一个 gadget 代表一个 usb slave 设备。这个数据结构是在底层控制器驱动中静态分配的。 Udc 驱动在调用 gadget驱动各接口函数时都会提供这个数据结构。
1147 /* FIXME this can't yet work right with SH … it has only
1148 * one configuration, numbered one.
1149 */
1150 if (gadget_is_sh (gadget))
1151 return -ENODEV ;
注意我们以前说过 gadget_is_* 系列函数提供了查询硬件能力的接口,这里用于判断是否是 SH 平台的 udc, 如果是, 直接出错返回: g_zero 驱动目前还不支持该平台。
1153 /* Bulk-only drivers like this one SHOULD be able to
1154 * autoconfigure on any sane usb controller driver,
1155 * but there may also be important quirks to address.
1156 */
1157 usb_ep_autoconfig_reset (gadget);
注意函数 usb_ep_autoconfig_reset 不是由底层 udc 驱动实现,而是我们以前提过的 helper 函数的一部分。该函数功能很简单:用于清空 gadget 的 端点列表。
1158 ep = usb_ep_autoconfig (gadget, &fs_source_desc );
1159 if (!ep) {
1160 autoconf_fail:
1161 printk (KERN_ERR "%s: can't autoconfigure on %s/n" ,
1162 shortname , gadget->name );
1163 return -ENODEV ;
1164 }
1165 EP_IN_NAME = ep->name ;
1166 ep->driver_data = ep; /* claim */
1167
1168 ep = usb_ep_autoconfig (gadget, &fs_sink_desc );
1169 if (!ep)
1170 goto autoconf_fail;
1171 EP_OUT_NAME = ep->name ;
1172 ep->driver_data = ep; /* claim */
函数 usb_ep_autoconfig 根据第二个参数所描述的限制条件,自动寻找适合条件的端点,并插入 gadget 的端点列表。这里 ep 是普通的数据端点,它的 driver_data 不需要存放特殊数据,那就保存一下自己的地址吧。(后面我们将看到 ep0 的 driver_data 放的是 zero_driver 的特殊数据)。我们看一下 fs_source_desc:
296 static struct usb_endpoint_descriptor
297 fs_source_desc = {
298 .bLength = USB_DT_ENDPOINT_SIZE ,
299 .bDescriptorType = USB_DT_ENDPOINT ,
300
301 .bEndpointAddress = USB_DIR_IN ,
302 .bmAttributes = USB_ENDPOINT_XFER_BULK ,
303 };
可见该描述符描述的是一个类型为 BULK, 方向为 IN 的端点。 fs_sink_desc 的定义类似,描述一个类型为 BULK, 方向为 OUT 的端点。下面继续看 zero_bind 的代码。
1174 gcnum = usb_gadget_controller_number (gadget);
1175 if (gcnum >= 0)
1176 device_desc .bcdDevice = cpu_to_le16 (0x0200 + gcnum);
1177 else {
1178 /* gadget zero is so simple (for now, no altsettings) that
1179 * it SHOULD NOT have problems with bulk-capable hardware.
1180 * so warn about unrcognized controllers, don't panic.
1181 *
1182 * things like configuration and altsetting numbering
1183 * can need hardware-specific attention though.
1184 */
1185 printk (KERN_WARNING "%s: controller '%s' not recognized/n" ,
1186 shortname , gadget->name );
1187 device_desc .bcdDevice = __constant_cpu_to_le16 (0x9999);
1188 }
每一个 udc 驱动被分配了一个编号,用作该设备描述符里的 bcd 码。 如果没有分配,没办法,就将就着用 0x9999 吧。
1191 /* ok, we made sense of the hardware … */
1192 dev = kzalloc (sizeof(*dev ), GFP_KERNEL );
1193 if (!dev )
1194 return -ENOMEM ;
1195 spin_lock_init (&dev ->lock );
1196 dev ->gadget = gadget;
1197 set_gadget_data (gadget, dev );
1198
stuct gadget 维护所有 gadget 驱动共性的内容,个性的数据则由各 gadget 驱动各自定义,对于 zero, 它定义了 zero_dev. 分配后存放在 gadget 结构的某个角落里:gadget.dev.driver_data 。 zero_dev 定义如下:
119 struct zero_dev {
120 spinlock_t lock ;
121 struct usb_gadget *gadget;
122 struct usb_request *req; /* for control responses */
124 /* when configured, we have one of two configs:
125 * – source data (in to host) and sink it (out from host)
126 * – or loop it back (out from host back in to host)
127 */
128 u8 config ;
129 struct usb_ep *in_ep, *out_ep;
131 /* autoresume timer */
132 struct timer_list resume;
133 };
这里 resume 是用于唤醒 host 的 timer 的列表, config 表示我们当前使用第几个 configuration. 其它含义自明。下面继续看 zero bind 代码。
1199 /* preallocate control response and buffer */
1200 dev ->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL );
1201 if (!dev ->req)
1202 goto enomem;
1203 dev ->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ ,
1204 &dev ->req->dma , GFP_KERNEL );
1205 if (!dev ->req->buf )
1206 goto enomem;
1207
1208 dev ->req->complete = zero_setup_complete ;
1209
这几行代码分配用于控制传输的请求 / 数据缓冲以及结束函数。控制传输是每个 gadget 驱动要使用的传输方式,这里及早分配。结束函数 zero_setup_complete 只是打印一下状态,我们就不贴出了。
1210 device_desc .bMaxPacketSize0 = gadget->ep0->maxpacket;
这里根据底层的数据初始化设备描述符里端点 0 (控制端点)的最大包大小。
1212 #ifdef CONFIG_USB_GADGET_DUALSPEED
1213 /* assume ep0 uses the same value for both speeds … */
1214 dev_qualifier .bMaxPacketSize0 = device_desc .bMaxPacketSize0;
1215
1216 /* and that all endpoints are dual-speed */
1217 hs_source_desc .bEndpointAddress = fs_source_desc .bEndpointAddress;
1218 hs_sink_desc .bEndpointAddress = fs_sink_desc .bEndpointAddress;
1219 #endif
高速设备需要的额外的描述符,我们对某些字段进行初始化。
1221 if (gadget->is_otg) {
1222 otg_descriptor .bmAttributes |= USB_OTG_HNP ,
1223 source_sink_config .bmAttributes |= USB_CONFIG_ATT_WAKEUP ;
1224 loopback_config .bmAttributes |= USB_CONFIG_ATT_WAKEUP ;
1225 }
如果是 otg 设备,则需要在描述符里设置相关特性。
1227 usb_gadget_set_selfpowered (gadget);
能运行 Linux Gadget 驱动的设备一般电池供电,也就是 selfpowered 。
1229 init_timer (&dev ->resume);
1230 dev ->resume.function = zero_autoresume ;
1231 dev ->resume.data = (unsigned long) dev ;
1232 if (autoresume ) {
1233 source_sink_config .bmAttributes |= USB_CONFIG_ATT_WAKEUP ;
1234 loopback_config .bmAttributes |= USB_CONFIG_ATT_WAKEUP ;
1235 }
这段代码跟自动唤醒 host 有关, 不深究。
1237 gadget->ep0->driver_data = dev ;
多记一份 zero_dev 的地址, 方便使用。
1239 INFO (dev , "%s, version: " DRIVER_VERSION "/n" , longname );
1240 INFO (dev , "using %s, OUT %s IN %s/n" , gadget->name ,
1241 EP_OUT_NAME , EP_IN_NAME );
1242
1243 snprintf (manufacturer , sizeof manufacturer , "%s %s with %s" ,
1244 init_utsname ()->sysname, init_utsname ()->release ,
1245 gadget->name );
1246
1247 return 0;
1248
1249 enomem:
1250 zero_unbind (gadget);
1251 return -ENOMEM ;
1252 }
自此 zero_bind 分析完毕。它主要是为 gadget 驱动找到了合适的端点,并且初始化了设备相关结构 : zero_dev. 从而把 gadget 驱动和 udc 驱动仅仅地绑定在一起。 看到现在,我们还没有感受到 gadget 驱动的真正意义, 前面的函数就像一座座桥梁,走过这些桥梁,我们终于来到美丽的湖心小岛:zero_setup 。
函数 zero_setup
zero_setup 完成控制传输的大部分功能。比如获取各种描述符、设置配置等。 Host 首先通过控制传输和设备进行通信,告诉设备它底下要干什么。 Zero gadget 驱动比较简单,在主机进行 set configuration 后,就会在 IN/OUT 端点上准备好数据,供主机去用。并且通过 call 函数,在主机使用完前面准备好的数据后,继续插入请求,这样,主机就可以源源不断的对我们这个设备进行读写操作。以下开始看代码。
917 static int
918 zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl )
919 {
照例,我们得到 usb_gadget 结构,同时,我们的第二个参数是 usb_ctrlrequest 结构:
140 struct usb_ctrlrequest {
141 __u8 bRequestType;
142 __u8 bRequest;
143 __le16 wValue;
144 __le16 wIndex;
145 __le16 wLength;
146 } __attribute__ ((packed));
具体含义请参考 Usb spec Ch9 。 这里结构名字有点误导, usb_ctrlrequest 代表的 是主机传过来的控制请求。和后面的 usb_request 有较大区别。 usb_request 代表放到端点的队列里等待主机过来读写的一个个数据包。下面我们继续看 zero_setup 函数代码。
920 struct zero_dev *dev = get_gadget_data (gadget);
921 struct usb_request *req = dev ->req;
922 int value = -EOPNOTSUPP ;
923 u16 w_index = le16_to_cpu (ctrl ->wIndex);
924 u16 w_value = le16_to_cpu (ctrl ->wValue);
925 u16 w_length = le16_to_cpu (ctrl ->wLength);
获得我们在 bind 函数分配的 zero_dev, usb_request , 以及由主机传过来的“请求”的各字段。
927 /* usually this stores reply data in the pre-allocated ep0 buffer,
928 * but config change events will reconfigure hardware.*/
930 req->zero = 0;
931 switch (ctrl ->bRequest) {
932
933 case USB_REQ_GET_DESCRIPTOR :
934 if (ctrl ->bRequestType != USB_DIR_IN )
935 goto unknown ;
请求各种描述符,当然需要是 IN 类型的请求。
936 switch (w_value >> 8) {
938 case USB_DT_DEVICE :
939 value = min (w_length, (u16 ) sizeof device_desc );
940 memcpy (req->buf , &device_desc , value );
941 break;
942 #ifdef CONFIG_USB_GADGET_DUALSPEED
943 case USB_DT_DEVICE_QUALIFIER :
944 if (!gadget->is_dualspeed)
945 break;
946 value = min (w_length, (u16 ) sizeof dev_qualifier );
947 memcpy (req->buf , &dev_qualifier , value );
948 break;
对应 USB 2.0 Spec CH9, 以上代码很容易理解。 每一个描述符使用 struct usb_device_descriptor 描述,比如, 设备描述符:
222 static struct usb_device_descriptor
223 device_desc = {
224 .bLength = sizeof device_desc ,
225 .bDescriptorType = USB_DT_DEVICE ,
226
227 .bcdUSB = __constant_cpu_to_le16 (0x0200),
228 .bDeviceClass = USB_CLASS_VENDOR_SPEC , 0xff
229
230 . idVendor = __constant_cpu_to_le16 ( DRIVER_VENDOR_NUM ),
231 . idProduct = __constant_cpu_to_le16 ( DRIVER_PRODUCT_NUM ),
232 . iManufacturer = STRING_MANUFACTURER , 25 , 厂商描述符
233 . iProduct = STRING_PRODUCT , 42 ,厂品描述符
234 . iSerialNumber = STRING_SERIAL , 101, 序列号
235 .bNumConfigurations = 2,
236 };
950 case USB_DT_OTHER_SPEED_CONFIG :
951 if (!gadget->is_dualspeed)
952 break;
953 // FALLTHROUGH
954 #endif /* CONFIG_USB_GADGET_DUALSPEED */
955 case USB_DT_CONFIG :
956 value = config_buf (gadget, req->buf ,
957 w_value >> 8,
958 w_value & 0xff);
959 if (value >= 0)
960 value = min (w_length, (u16 ) value );
961 break;
配置描述符比较复杂,会返回该配置里的接口,端点等信息。配置描述符由:struct usb_descriptor_header [] 表达, 而且高速/ 全速设备的配置描述符是不一样。比如,高速loopback 配置的配置描述符为:
378 static const struct usb_descriptor_header * hs_loopback_function [] = {
379 (struct usb_descriptor_header *) & otg_descriptor ,
380 (struct usb_descriptor_header *) & loopback_intf ,
381 (struct usb_descriptor_header *) & hs_source_desc ,
382 (struct usb_descriptor_header *) & hs_sink_desc ,
383 NULL ,
384 };
可见,本质上,配置描述符是返回一组描述符。下面看一下配置描述符是如何生成的。
432 static int
433 config_buf (struct usb_gadget *gadget,
434 u8 * buf , u8 type , unsigned index )
435 {
436 int is_source_sink;
437 int len ;
438 const struct usb_descriptor_header **function;
439 #ifdef CONFIG_USB_GADGET_DUALSPEED
440 int hs = (gadget-> speed == USB_SPEED_HIGH);
441 #endif
442
443 /* two configurations will always be index 0 and index 1 */
444 if ( index > 1)
445 return – EINVAL ;
446 is_source_sink = loopdefault ? ( index == 1) : ( index == 0);
447
448 #ifdef CONFIG_USB_GADGET_DUALSPEED
449 if ( type == USB_DT_OTHER_SPEED_CONFIG )
450 hs = !hs;
451 if (hs)
452 function = is_source_sink
453 ? hs_source_sink_function
454 : hs_loopback_function ;
455 else
456 #endif
457 function = is_source_sink
458 ? fs_source_sink_function
459 : fs_loopback_function ;
460
461 /* for now, don't advertise srp-only devices */
462 if (!gadget->is_otg)
463 function++;
464
465 len = usb_gadget_config_buf (is_source_sink
466 ? & source_sink_config
467 : & loopback_config ,
468 buf , USB_BUFSIZ , function);
469 if ( len < 0)
470 return len ;
471 ((struct usb_config_descriptor *) buf )->bDescriptorType = type ;
472 return len ;
473 }
代码很简单, config_buf 函数根据当前是否是高速设备,以及是否是 otg 设备,选择合适的 configuration( souce sink config or loopback config) , 调用usb_gadget_config_buf 生成最终的配置描述符。可以想象 usb_gadget_config_buf 的实现非常简单 : 根据传过来的 描述符列表 ( 以 NULL 指针结束 ) ,使用 memcpy 之类见每个描述符的内容拷贝到 buf 里。 下面我们继续看 zero_setup 函数。
963 case USB_DT_STRING :
964 /* wIndex == language code.
965 * this driver only handles one language, you can
966 * add string tables for other languages, using
967 * any UTF-8 characters
968 */
969 value = usb_gadget_get_string (&stringtab ,
970 w_value & 0xff, req->buf );
971 if (value >= 0)
972 value = min (w_length, (u16 ) value );
973 break;
974 }
975 break;
976
根据 host 传递过来的索引,响应相应的字符串。Zero 驱动的字符串描述符则只支持一种语言(0409, en-us ):
409 static struct usb_gadget_strings stringtab = {
410 .language = 0x0409, /* en-us */
411 .strings = strings ,
412 };
399 /* static strings, in UTF-8 */
400 static struct usb_string strings [] = {
401 { STRING_MANUFACTURER , manufacturer , },
402 { STRING_PRODUCT , longname , },
403 { STRING_SERIAL , serial , },
404 { STRING_LOOPBACK , loopback , },
405 { STRING_SOURCE_SINK , source_sink , },
406 { } /* end of list */
407 };
有点像应用层(比如 vc )为了支持多语言而独立出来的字符串资源。事实上就是这样!我们可以很容易再增加一种语言。下面我们继续看 zero_setup 函数。
977 /* currently two configs, two speeds */
978 case USB_REQ_SET_CONFIGURATION :
979 if (ctrl ->bRequestType != 0)
980 goto unknown ;
981 if (gadget->a_hnp_support)
982 DBG (dev , "HNP available/n" );
983 else if (gadget->a_alt_hnp_support)
984 DBG (dev , "HNP needs a different root port/n" );
985 else
986 VDBG (dev , "HNP inactive/n" );
987 spin_lock (&dev ->lock );
988 value = zero_set_config (dev , w_value, GFP_ATOMIC );
989 spin_unlock (&dev ->lock );
990 break;
设置设备的当前配置,到这里,才凌空一脚,将设备带入数据传输状态,我们先把zero_setup 看完,再仔细看函数 zero_set_config 。
991 case USB_REQ_GET_CONFIGURATION :
992 if (ctrl ->bRequestType != USB_DIR_IN )
993 goto unknown ;
994 *(u8 *)req->buf = dev ->config ;
995 value = min (w_length, (u16 ) 1);
996 break;
获取设备的当前配置
998 /* until we add altsetting support, or other interfaces,
999 * only 0/0 are possible. pxa2xx only supports 0/0 (poorly)
1000 * and already killed pending endpoint I/O.
1001 */
1002 case USB_REQ_SET_INTERFACE :
1003 if (ctrl ->bRequestType != USB_RECIP_INTERFACE )
1004 goto unknown ;
1005 spin_lock (&dev ->lock );
1006 if (dev ->config && w_index == 0 && w_value == 0) {
1007 u8 config = dev ->config ;
1008
1009 /* resets interface configuration, forgets about
1010 * previous transaction state (queued bufs, etc)
1011 * and re-inits endpoint state (toggle etc)
1012 * no response queued, just zero status == success.
1013 * if we had more than one interface we couldn't
1014 * use this "reset the config" shortcut.
1015 */
1016 zero_reset_config (dev );
1017 zero_set_config (dev , config , GFP_ATOMIC );
1018 value = 0;
1019 }
1020 spin_unlock (&dev ->lock );
1021 break;
设置接口,由于我们每个configuration 只有一个接口,所以这里的效果跟前面设置配置类似。
由于 zero_set_config 函数会调用 zero_reset_config, 所以这里应该可以不调用 zero_reset_config.
1022 case USB_REQ_GET_INTERFACE :
1023 if (ctrl ->bRequestType != (USB_DIR_IN |USB_RECIP_INTERFACE ))
1024 goto unknown ;
1025 if (!dev ->config )
1026 break;
1027 if (w_index != 0) {
1028 value = -EDOM ;
1029 break;
1030 }
1031 *(u8 *)req->buf = 0;
1032 value = min (w_length, (u16 ) 1);
1033 break;
1034
获取设备的当前配置的当前接口。
1035 /*
1036 * These are the same vendor-specific requests supported by
1037 * Intel's USB 2.0 compliance test devices. We exceed that
1038 * device spec by allowing multiple-packet requests.
1039 */
1040 case 0x5b: /* control WRITE test — fill the buffer */
1041 if (ctrl ->bRequestType != (USB_DIR_OUT |USB_TYPE_VENDOR ))
1042 goto unknown ;
1043 if (w_value || w_index)
1044 break;
1045 /* just read that many bytes into the buffer */
1046 if (w_length > USB_BUFSIZ )
1047 break;
1048 value = w_length;
1049 break;
1050 case 0x5c: /* control READ test — return the buffer */
1051 if (ctrl ->bRequestType != (USB_DIR_IN |USB_TYPE_VENDOR ))
1052 goto unknown ;
1053 if (w_value || w_index)
1054 break;
1055 /* expect those bytes are still in the buffer; send back */
1056 if (w_length > USB_BUFSIZ
1057 || w_length != req->length )
1058 break;
1059 value = w_length;
1060 break;
1061
根据协议,我们可以定制私有的类型,这里是 Intel 定义的测试类型,用于测试端点0 的数据收发。端点0 通常用于控制传输, 用它进行数据传输完全是为了测试目的。
1062 default:
1063 unknown :
1064 VDBG (dev ,
1065 "unknown control req%02x.%02x v%04x i%04x l%d/n" ,
1066 ctrl ->bRequestType, ctrl ->bRequest,
1067 w_value, w_index, w_length);
1068 }
1069
1070 /* respond with data transfer before status phase? */
1071 if (value >= 0) {
1072 req->length = value ;
1073 req->zero = value < w_length;
1074 value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC );
1075 if (value < 0) {
1076 DBG (dev , "ep_queue –> %d/n" , value );
1077 req->status = 0;
1078 zero_setup_complete (gadget->ep0, req);
1079 }
1080 }
如果有数据需要传给 Host, 则将其放到端点0 的传送队列。底层 udc 驱动会负责将其发给 host.
1082 /* device either stalls (value < 0) or reports success */
1083 return value ;
1084 }
函数 zero_setup 完成了 usb spec ch9 定义的很多功能。而我们前面介绍的 bulk-in/bulk-out 数据端点开始工作则是在 set configuration (或者 set interface )后,由 zero_set_config 函数触发。下面开始分析该函数。
函数zero_set_config
848 static int
849 zero_set_config (struct zero_dev *dev , unsigned number , gfp_t gfp_flags)
850 {
851 int result = 0;
852 struct usb_gadget *gadget = dev ->gadget;
853
854 if (number == dev ->config )
855 return 0;
862 zero_reset_config (dev );
863
函数 zero_reset_config 把所有的 端点置于 disable 状态。
864 switch (number ) {
865 case CONFIG_SOURCE_SINK :
866 result = set_source_sink_config (dev , gfp_flags);
867 break;
868 case CONFIG_LOOPBACK :
869 result = set_loopback_config (dev , gfp_flags);
870 break;
871 default:
872 result = -EINVAL ;
873 /* FALL THROUGH */
874 case 0:
875 return result ;
876 }
根据当前的配置,设置两种不同的传送方式。我们假定 host 设置的是 loopback 方式。另一种方式是类似的 ( 数据内容不同 ) 。
878 if (!result && (!dev ->in_ep || !dev ->out_ep))
879 result = -ENODEV ;
880 if (result )
881 zero_reset_config (dev );
882 else {
883 char *speed ;
884
885 switch (gadget->speed ) {
886 case USB_SPEED_LOW: speed = "low" ; break;
887 case USB_SPEED_FULL: speed = "full" ; break;
888 case USB_SPEED_HIGH: speed = "high" ; break;
889 default: speed = "?" ; break;
890 }
891
892 dev ->config = number ;
893 INFO (dev , "%s speed config #%d: %s/n" , speed , number ,
894 (number == CONFIG_SOURCE_SINK )
895 ? source_sink : loopback );
896 }
897 return result ;
898 }
一些善后处理。 下面我们看函数 set_loopback_config
函数 set_loopback_config
747 static int
748 set_loopback_config (struct zero_dev *dev , gfp_t gfp_flags)
749 {
750 int result = 0;
751 struct usb_ep *ep;
752 struct usb_gadget *gadget = dev ->gadget;
753
754 gadget_for_each_ep (ep, gadget) {
针对 gadget 端点列表的每一个端点进行操作。
755 const struct usb_endpoint_descriptor *d;
756
757 /* one endpoint writes data back IN to the host */
758 if (strcmp (ep->name , EP_IN_NAME ) == 0) {
759 d = ep_desc (gadget, &hs_source_desc , &fs_source_desc );
760 result = usb_ep_enable (ep, d);
761 if (result == 0) {
762 ep->driver_data = dev ;
763 dev ->in_ep = ep;
764 continue;
765 }
766
767 /* one endpoint just reads OUT packets */
768 } else if (strcmp (ep->name , EP_OUT_NAME ) == 0) {
769 d = ep_desc (gadget, &hs_sink_desc , &fs_sink_desc );
770 result = usb_ep_enable (ep, d);
771 if (result == 0) {
772 ep->driver_data = dev ;
773 dev ->out_ep = ep;
774 continue;
775 }
776
777 /* ignore any other endpoints */
778 } else
779 continue;
780
781 /* stop on error */
782 ERROR (dev , "can't enable %s, result %d/n" , ep->name , result );
783 break;
784 }
激活端点。并设置速度 ( 高速或者全速 ) 。
786 /* allocate a bunch of read buffers and queue them all at once.
787 * we buffer at most 'qlen' transfers; fewer if any need more
788 * than 'buflen' bytes each.
789 */
790 if (result == 0) {
791 struct usb_request *req;
792 unsigned i ;
793
794 ep = dev ->out_ep;
795 for (i = 0; i < qlen && result == 0; i ++) {
796 req = alloc_ep_req (ep, buflen );
797 if (req) {
798 req->complete = loopback_complete ;
799 result = usb_ep_queue (ep, req, GFP_ATOMIC );
800 if (result )
801 DBG (dev , "%s queue req –> %d/n" ,
802 ep->name , result );
803 } else
804 result = -ENOMEM ;
805 }
806 }
首先在 OUT 端点上挂一堆请求( usb_request ) , 等待主机向我们发送数据。等主机真正对我们进行 OUT 数据传输并且数据传完后,会调用 loopback_complete 回调函数。
807 if (result == 0)
808 DBG (dev , "qlen %d, buflen %d/n" , qlen , buflen );
809
810 /* caller is responsible for cleanup on error */
811 return result ;
812 }
下面看 函数 loopback_complete
函数 loopback_complete
698 static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
699 {
700 struct zero_dev *dev = ep->driver_data ;
701 int status = req->status ;
702
703 switch (status ) {
704
705 case 0: /* normal completion? */
706 if (ep == dev ->out_ep) {
707 /* loop this OUT packet back IN to the host */
708 req->zero = (req->actual < req->length );
709 req->length = req->actual;
710 status = usb_ep_queue (dev ->in_ep , req, GFP_ATOMIC );
711 if (status == 0)
712 return;
713
714 /* "should never get here" */
715 ERROR (dev , "can't loop %s to %s: %d/n" ,
716 ep->name , dev ->in_ep->name ,
717 status );
718 }
719
720 /* queue the buffer for some later OUT packet */
721 req->length = buflen ;
722 status = usb_ep_queue (dev ->out_ep , req, GFP_ATOMIC );
723 if (status == 0)
724 return;
725
726 /* "should never get here" */
727 /* FALLTHROUGH */
728
729 default:
730 ERROR (dev , "%s loop complete –> %d, %d/%d/n" , ep->name ,
731 status , req->actual, req->length );
732 /* FALLTHROUGH */
733
734 /* NOTE: since this driver doesn't maintain an explicit record
735 * of requests it submitted (just maintains qlen count), we
736 * rely on the hardware driver to clean up on disconnect or
737 * endpoint disable.
738 */
739 case -ECONNABORTED : /* hardware forced ep reset */
740 case -ECONNRESET : /* request dequeued */
741 case -ESHUTDOWN : /* disconnect from host */
742 free_ep_req (ep, req);
743 return;
744 }
745 }
如果 OUT 传输正常结束,则会将其放到 IN 端点的传输队列。
如果 IN 传输正常结束,则会将其放到 OUT 端点的传输队列。
这样,通过回调函数不断在两个队列 (IN/OUT) 之间切换这些请求 (usb_request), 就实现了在主机看来的 loopback 设备。
总结
Gadget 驱动的特殊性在于它是 host 端对等驱动的 slave, 而不是上层某个应用的 slave. 响应的,它是实现是很有意思的。我们没有看到 read/write 函数,也没有看到我们最常实现的 ioctl 函数, 而是把重点放在回调函数 zero_setup 上。 g_zero gadget 驱动实现了一个最简单的 bulk-in/bulk-out 功能,向我们展示了 gadget 驱动如果利用 gadget API 来完成数据传输功能。对于复杂的 gadget 驱动, setup 回调函数只是一个起点。
参考
USB 2.0 Spec
http://www.usb.org/developers/docs/
用 KFI 和 Graphviz 跟踪 / 优化内核代码
http://blog.csdn.net/colorant/archive/2008/07/09/2627493.aspx