此處將以zero.c爲例進行講解。linux
第一次接觸zero.c驅動的時候,是由於某項目須要,提供一種usb字符設備,但願可以經過字符設備打開,讀取和發送文件。當時能想到的就是zero.c文件,本打算按照zero驅動的編寫方式,本身編寫一個字符驅動,但後來爲了節省工做時間,直接修改zero驅動,增長了字符設備的註冊和操做函數。網絡
zero.c驅動提供了豐富的功能接口,既包含自收自發的loopback(迴環功能),又包含了主從通訊的source link功能。該兩功分別綁定各自的配置,配置在實際使用的過程當中,是不一樣共存的,只能切換操做,固然,若是你足夠厲害,將兩功能彙總到一個配置裏面,也不是不可能的事。該兩種功能的具體實現會在下面詳細介紹。app
zero.c驅動功能上主要是實現了兩個bulk端點,in和out,根據選定的配置,in和out針對性就不一樣了。可是若是你要是想和host端主機通訊,source link功能必然是完美的選擇,由於loopback顧明思意,就是採用的迴環功能。框架
在介紹zero.c驅動過的實現以前,先介紹下zero中相關的變量和函數。函數
variable : //該驅動涉及到的變量和結構體。 || autoresume || autoresume_interval_ || autoresume_step_ms || autoresume_timer //表示zero設備與resume操做相關。|| dev_strings //設備字符串描述符 || device_desc //設備描述符,惟一 || func_inst_lb //loopback功能實例 此處特別的重要 || func_inst_ss //source link功能實例,也特別的重要。 || func_lb //loopback接口,又稱功能 || func_ss //source link接口,又稱功能 || gzero_options //涉及到zero設備中packet和bulk_buf長度等|| longname //產品名稱|| loopdefault //是否支持loopback功能經過該變量斷定,爲0表示選擇source link功能。 || max_autoresume //最長的自動恢復時間,與定時器設置相關 || otg_desc //關於otg功能的 || otg_descriptor || serial /Serial 變量存儲的是設備序列號,對於一個非正式設備,顯得不是那麼重要,隨便填充一下 || sourcesink_driver //基本上後綴命名的driver表示是usb config || strings_dev //字符串描述符 || stringtab_dev //gadget字符串描述符,包括字符串描述符,以及支持的語種。默認是英文。 || zero_driver //usb_composite_driver function || cleanup //卸載驅動函數。 || init //驅動註冊函數。 || ss_config_setup //枚舉響應函數,只有source link功能支持。 || zero_autoresum //定時器調用函數 || zero_bind //沒有綁定,就沒有各類配置和接口的實現,也就沒有驅動和設備的綁定 || zero_resume //我的認爲主要是省電模式採用,設備處於空閒時,進入掛起狀態,被喚醒後自動回覆正常狀態
|| zero_suspend //設備掛起。
|| zero_unbind //是否功能和功能實例。
之因此介紹zero驅動的相關變量、結構體和函數主要是爲了對驅動總體框架有所瞭解。在分析該驅動的過程當中,咱們主要關注那些點,以及這些是怎麼封裝的,這樣會對咱們改zero驅動會有很大的幫助。oop
1=======模塊的註冊和卸載。此處不用多講,個人另外一篇文章linux usb gadget框架概述已經較爲詳細的介紹了驅動的註冊過程。測試
403 static __refdata struct usb_composite_driver zero_driver = { 404 .name = "zero", 405 .dev = &device_desc, 406 .strings = dev_strings, 407 .max_speed = USB_SPEED_SUPER, //此處還支持usb3.0?沒有測試過。 408 .bind = zero_bind, 409 .unbind = zero_unbind, 410 .suspend = zero_suspend, 411 .resume = zero_resume, 412 }; 413 414 MODULE_AUTHOR("David Brownell"); 415 MODULE_LICENSE("GPL"); 416 417 static int __init init(void) 418 { 419 return usb_composite_probe(&zero_driver); 420 }
421 module_init(init); 422 423 static void __exit cleanup(void) 424 { 425 usb_composite_unregister(&zero_driver); 426 } 427 module_exit(cleanup);
2=====填充設備描述符。this
112 static struct usb_device_descriptor device_desc = { 113 .bLength = sizeof device_desc, 114 .bDescriptorType = USB_DT_DEVICE,//描述符類型,此處表示設備描述符,非接口描述符 115 116 .bcdUSB = cpu_to_le16(0x0200), 117 .bDeviceClass = USB_CLASS_VENDOR_SPEC, //#define USB_CLASS_VENDOR_SPEC 0xff 表示產商自定義類設備 118 119 .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), 120 .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), 121 .bNumConfigurations = 2, //介紹該設備有幾個配置,此處寫的兩個,真好是loopback和source link兩個配置。 122 };
3=====填充字符描述符。基本上usb_gadget_strings都是這個德行,封裝三層,最後填充到zero_driver的.strings = dev_strings,中去。spa
150 static struct usb_string strings_dev[] = { 151 [USB_GADGET_MANUFACTURER_IDX].s = "", 152 [USB_GADGET_PRODUCT_IDX].s = longname, 153 [USB_GADGET_SERIAL_IDX].s = serial, 154 [USB_GZERO_SS_DESC].s = "source and sink data", 155 [USB_GZERO_LB_DESC].s = "loop input to output", 156 { } /* end of list */ 157 }; 158 159 static struct usb_gadget_strings stringtab_dev = { 160 .language = 0x0409, /* en-us */ 161 .strings = strings_dev, 162 }; 163 164 static struct usb_gadget_strings *dev_strings[] = { 165 &stringtab_dev, 166 NULL, 167 };
==========填充配置描述符。loopback_driver&sourcesink_driver設計
242 static struct usb_configuration sourcesink_driver = { 243 .label = "source/sink", //標籤在主機枚舉的時候獲取,若是主機是window,能夠在管理/設備管理器中找到 244 .setup = ss_config_setup, //setup主要是響應枚舉過程當中控制請求某些特效的操做。 245 .bConfigurationValue = 3, //當使用SetConfiguration和GetConfiguration請求時所指定的配置索引值。這個在響應枚舉過程是十分重要的。 246 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, //自供電 247 /* .iConfiguration = DYNAMIC */ 248 }; 220 static struct usb_configuration loopback_driver = { 221 .label = "loopback", 222 .bConfigurationValue = 2, 223 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 224 /* .iConfiguration = DYNAMIC */ 225 };
==========填充接口描述符。func_ss&func_lb
該接口的實現挺有技巧的,下面詳細講述之。
227 static struct usb_function *func_ss; 228 static struct usb_function_instance *func_inst_ss; //視乎編寫一個gadget驅動的通用方法須要填充一個功能實例。 269 static struct usb_function *func_lb; 270 static struct usb_function_instance *func_inst_lb;
//首先,填充usb_function_instance 這個結構體。
func_inst_ss = usb_get_function_instance("SourceSink");
func_inst_lb = usb_get_function_instance("Loopback");
38 struct usb_function_instance *usb_get_function_instance(const char *name) //此處是怎麼經過字符串獲得的功能實例呢?
39 {
40 struct usb_function_instance *fi;
41 int ret;
42
43 fi = try_get_usb_function_instance(name);
44 if (!IS_ERR(fi))
45 return fi;
46 ret = PTR_ERR(fi);
47 if (ret != -ENOENT)
48 return fi;
49 ret = request_module("usbfunc:%s", name);
50 if (ret < 0)
51 return ERR_PTR(ret);
52 return try_get_usb_function_instance(name); //關鍵在於這個函數。
53 }
11 static struct usb_function_instance *try_get_usb_function_instance(const char *name)
12 {
13 struct usb_function_driver *fd;
14 struct usb_function_instance *fi;
15
16 fi = ERR_PTR(-ENOENT);
17 mutex_lock(&func_lock);
18 list_for_each_entry(fd, &func_list, list) { //便利全部的功能鏈表,經過功能鏈表獲取功能驅動,那功能驅動從哪裏來的?那就設計到每一個功能驅動的註冊了。
19
20 if (strcmp(name, fd->name))
21 continue;
22
23 if (!try_module_get(fd->mod)) {
24 fi = ERR_PTR(-EBUSY);
25 break;
26 }
27 fi = fd->alloc_inst(); //功能實例是在這裏生成的。
28 if (IS_ERR(fi))
29 module_put(fd->mod);
30 else
31 fi->fd = fd;
32 break;
33 }
34 mutex_unlock(&func_lock);
35 return fi;
36 }
那如今問題的關鍵點是在於找到usb_function_driver這個結構體,驅動確定是須要調用註冊函數進行註冊的,功能驅動確定是在各自功能實現文件裏。
f_sourcesink.c f_loopback.c
usb_function_register(&SourceSinkusb_func); 90 int usb_function_register(struct usb_function_driver *newf) 91 { 92 struct usb_function_driver *fd; 93 int ret; 94 95 ret = -EEXIST; 96 97 mutex_lock(&func_lock); 98 list_for_each_entry(fd, &func_list, list) { 99 if (!strcmp(fd->name, newf->name)) 100 goto out; 101 } 102 ret = 0; 103 list_add_tail(&newf->list, &func_list); //從該函數能夠看出,該註冊函數正好是講功能實例結構體中的鏈表加入全局鏈表func_list中,這樣經過list_for_entry就能夠獲取實例了
104 out:
105 mutex_unlock(&func_lock);
106 return ret; 107 }
那SourceSinkusb_func這個變量從哪裏來呢?用ag搜索了整個內核目錄都沒有找到,這個時候不得很差好分析linux中宏定義的厲害了。
1224 DECLARE_USB_FUNCTION(SourceSink, source_sink_alloc_inst, 1225 source_sink_alloc_func); 489 #define DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \ 490 static struct usb_function_driver _name ## usb_func = { \ //這個地方就不用過多的介紹了吧。 491 .name = __stringify(_name), \ 492 .mod = THIS_MODULE, \ 493 .alloc_inst = _inst_alloc, \ //因此在try_get_usb_function_instance函數中其實才是真正的開始對功能實例進行初始化。 494 .alloc_func = _func_alloc, \ //usb_get_function其實也是調用的該函數實現得功能的初始化。 495 }; \ 496 MODULE_ALIAS("usbfunc:"__stringify(_name));
下面在再來看一下alloc_func作了哪些操做。
865 static struct usb_function *source_sink_alloc_func( 866 struct usb_function_instance *fi) 867 { 868 struct f_sourcesink *ss; 869 struct f_ss_opts *ss_opts; 870 871 ss = kzalloc(sizeof(*ss), GFP_KERNEL); 872 if (!ss) 873 return NULL; 874 875 ss_opts = container_of(fi, struct f_ss_opts, func_inst); 876 877 mutex_lock(&ss_opts->lock); 878 ss_opts->refcnt++; 879 mutex_unlock(&ss_opts->lock); 880 881 pattern = ss_opts->pattern; 882 isoc_interval = ss_opts->isoc_interval; 883 isoc_maxpacket = ss_opts->isoc_maxpacket; 884 isoc_mult = ss_opts->isoc_mult; 885 isoc_maxburst = ss_opts->isoc_maxburst; 886 buflen = ss_opts->bulk_buflen; 887 888 ss->function.name = "source/sink"; //填充功能名稱 889 ss->function.bind = sourcesink_bind;//主要實現了設備和驅動的綁定,已經端點的初始化的操做 890 ss->function.set_alt = sourcesink_set_alt;//這個會根據配置中功能的前後順序,將某個功能配置爲0 891 ss->function.get_alt = sourcesink_get_alt; 892 ss->function.disable = sourcesink_disable; 893 ss->function.setup = sourcesink_setup; 894 ss->function.strings = sourcesink_strings; 895 896 ss->function.free_func = sourcesink_free_func; 897 898 return &ss->function; 899 }
==========填充端點描述符。 //端點描述符有兩種一個是支持全是一種是支持高速,主要針對host端是否支持來定,在bind函數中,將其加入function中。
97 static struct usb_endpoint_descriptor fs_source_desc = { 98 .bLength = USB_DT_ENDPOINT_SIZE, 99 .bDescriptorType = USB_DT_ENDPOINT, 100 101 .bEndpointAddress = USB_DIR_IN, 102 .bmAttributes = USB_ENDPOINT_XFER_BULK, 103 }; 104 105 static struct usb_endpoint_descriptor fs_sink_desc = { 106 .bLength = USB_DT_ENDPOINT_SIZE, 107 .bDescriptorType = USB_DT_ENDPOINT, 108 109 .bEndpointAddress = USB_DIR_OUT, 110 .bmAttributes = USB_ENDPOINT_XFER_BULK, 111 }; 113 static struct usb_endpoint_descriptor fs_iso_source_desc = { 114 .bLength = USB_DT_ENDPOINT_SIZE, 115 .bDescriptorType = USB_DT_ENDPOINT, 116 117 .bEndpointAddress = USB_DIR_IN, 118 .bmAttributes = USB_ENDPOINT_XFER_ISOC, 119 .wMaxPacketSize = cpu_to_le16(1023), 120 .bInterval = 4, 121 }; 122 123 static struct usb_endpoint_descriptor fs_iso_sink_desc = { 124 .bLength = USB_DT_ENDPOINT_SIZE, 125 .bDescriptorType = USB_DT_ENDPOINT, 126 127 .bEndpointAddress = USB_DIR_OUT, 128 .bmAttributes = USB_ENDPOINT_XFER_ISOC, 129 .wMaxPacketSize = cpu_to_le16(1023), 130 .bInterval = 4, 131 }; 133 static struct usb_descriptor_header *fs_source_sink_descs[] = { 134 (struct usb_descriptor_header *) &source_sink_intf_alt0, //在枚舉過程當中,都是經過usb_descriptor_header指針獲取的。 135 (struct usb_descriptor_header *) &fs_sink_desc, 136 (struct usb_descriptor_header *) &fs_source_desc, 137 (struct usb_descriptor_header *) &source_sink_intf_alt1, 138 #define FS_ALT_IFC_1_OFFSET 3 139 (struct usb_descriptor_header *) &fs_sink_desc, 140 (struct usb_descriptor_header *) &fs_source_desc, 141 (struct usb_descriptor_header *) &fs_iso_sink_desc, 142 (struct usb_descriptor_header *) &fs_iso_source_desc, 143 NULL, 144 };
至此,從驅動註冊,各類配置描述符的初始化和實現已經講完,是否是感受什麼也沒講明白,那是由於你不熟悉gadaget驅動的註冊和枚舉響應過程,下面將花大量的篇幅介紹gadget設備的枚舉過程。
枚舉過程主要分爲以下幾個步驟:
要了解gadget驅動的枚舉過程,就必須瞭解usb設備的中斷響應。要了解usb的中斷響應就必須知道usb控制的註冊過程,由於中斷的註冊實在控制器的註冊中完成的。
下面將花少許篇幅介紹下udc的註冊過程,以omap_udc.c爲例進行講解。
194 static struct platform_device udc_device = {
195 .name = "omap_udc",
196 .id = -1,
197 .dev = {
198 .dma_mask = &udc_dmamask,
199 .coherent_dma_mask = 0xffffffff,
200 },
201 .num_resources = ARRAY_SIZE(udc_resources),
202 .resource = udc_resources,
203 };
114 static const char driver_name[] = "omap_udc";//此處是平臺設備可以註冊成功的關鍵,平臺設備通常在板級信息中註冊。 3026 static struct platform_driver udc_driver = { 3027 .probe = omap_udc_probe, 3028 .remove = omap_udc_remove, 3029 .suspend = omap_udc_suspend, 3030 .resume = omap_udc_resume, 3031 .driver = { 3032 .owner = THIS_MODULE, 3033 .name = (char *) driver_name, 3034 }, 3035 };
一當內核查找到平臺設備和驅動設備中名稱匹配,就會加劇驅動,調用驅動probe函數
2731 static int omap_udc_probe(struct platform_device *pdev) 2732 { 2733 int status = -ENODEV; 2734 int hmc; 2735 struct usb_phy *xceiv = NULL; 2736 const char *type = NULL; 2737 struct omap_usb_config *config = pdev->dev.platform_data; 2738 struct clk *dc_clk = NULL; 2739 struct clk *hhc_clk = NULL; 2740 2741 if (cpu_is_omap7xx()) 2742 use_dma = 0; 2743 2744 /* NOTE: "knows" the order of the resources! */ 2745 if (!request_mem_region(pdev->resource[0].start, 2746 pdev->resource[0].end - pdev->resource[0].start + 1, 2747 driver_name)) { 2748 DBG("request_mem_region failed\n"); 2749 return -EBUSY; 2750 } 。。。。。。。。。。。 2879 /* USB "non-iso" IRQ (PIO for all but ep0) */ 2880 status = request_irq(pdev->resource[2].start, omap_udc_pio_irq, //最關鍵的函數,一當host發起任何從設備相關的操做,都會調用該函數。 2881 0, "omap_udc pio", udc); 2882 if (status != 0) { 2883 ERR("can't get irq %d, err %d\n", 2884 (int) pdev->resource[2].start, status); 2885 goto cleanup2; 2886 }
1819 static irqreturn_t omap_udc_irq(int irq, void *_udc) 1820 { 1821 struct omap_udc *udc = _udc; 1822 u16 irq_src; 1823 irqreturn_t status = IRQ_NONE; 1824 unsigned long flags; 1825 1826 spin_lock_irqsave(&udc->lock, flags); 1827 irq_src = omap_readw(UDC_IRQ_SRC); 1828 1829 /* Device state change (usb ch9 stuff) */ 1830 if (irq_src & UDC_DS_CHG) { 1831 devstate_irq(_udc, irq_src); 1832 status = IRQ_HANDLED; 1833 irq_src &= ~UDC_DS_CHG; 1834 } 1835 1836 /* EP0 control transfers */ 1837 if (irq_src & (UDC_EP0_RX|UDC_SETUP|UDC_EP0_TX)) {//針對枚舉過程,中斷源確定是控制端點0發送過來的。 1838 ep0_irq(_udc, irq_src);//若是是控制端點,則調用端點0中斷函數響應中斷。 1839 status = IRQ_HANDLED; 1840 irq_src &= ~(UDC_EP0_RX|UDC_SETUP|UDC_EP0_TX); 1841 }
//這個地方不對這個中斷函數進行多講,主要介紹其枚舉響應分支。
1667 default: 1668 delegate: 1669 /* activate the ep0out fifo right away */ 1670 if (!udc->ep0_in && w_length) { 1671 omap_writew(0, UDC_EP_NUM); 1672 omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); 1673 } 1674 1675 /* gadget drivers see class/vendor specific requests, 1676 ┊* {SET,GET}_{INTERFACE,DESCRIPTOR,CONFIGURATION}, 1677 ┊* and more 1678 ┊*/ 1679 VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n", 1680 u.r.bRequestType, u.r.bRequest, 1681 w_value, w_index, w_length); 1682 1683 #undef w_value 1684 #undef w_index 1685 #undef w_length 1686 1687 /* The gadget driver may return an error here, 1688 ┊* causing an immediate protocol stall. 1689 ┊* 1690 ┊* Else it must issue a response, either queueing a 1691 ┊* response buffer for the DATA stage, or halting ep0 1692 ┊* (causing a protocol stall, not a real halt). A 1693 ┊* zero length buffer means no DATA stage. 1694 ┊* 1695 ┊* It's fine to issue that response after the setup() 1696 ┊* call returns, and this IRQ was handled. 1697 ┊*/ 1698 udc->ep0_setup = 1; 1699 spin_unlock(&udc->lock); 1700 status = udc->driver->setup(&udc->gadget, &u.r); 這個函數可不是zero.c中那個setup函數,而是composite.c中的setup函數。下面咱們具體分析之。
=======枚舉過程的關鍵性函數。
在介紹該函數時,先介紹下相當重要的一個結構體,usb_request,該結構體就是數據發送和接受的載體,相似於網絡中的skb.
90 struct usb_request { 91 void *buf; //須要傳輸的數據都會在此填充。 92 unsigned length; //buf長度 93 dma_addr_t dma; //與dma操做相關的 94 95 struct scatterlist *sg; //視乎是分散彙集表鄙人不是很明白。 96 unsigned num_sgs; //如上 97 unsigned num_mapped_sgs; //如上 98 99 unsigned stream_id:16; //The stream id, when USB3.0 bulk streams are being used 100 unsigned no_interrupt:1; //If true, hints that no completion irq is needed. Helpful sometimes with deep request queues that are handled directly by DMA controllers. 101 unsigned zero:1; //是不是0包。 102 unsigned short_not_ok:1; //對於0包,斷定該報是否容許其爲錯包 103 104 void (*complete)(struct usb_ep *ep, //包發送完成後,會調用該函數。 105 struct usb_request *req); 106 void *context; //很簡單 107 struct list_head list; //同一類型的usb_request 108 109 int status; //當前狀態,Reports completion code, zero or a negative errno. 110 unsigned actual; //實際傳輸包的長度。 111 };
1227 composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) 1228 { 1229 struct usb_composite_dev *cdev = get_gadget_data(gadget); 1230 struct usb_request *req = cdev->req; //全部的數據傳輸都是靠usb_request函數完成的。 1231 int value = -EOPNOTSUPP; 1232 int status = 0; 1233 u16 w_index = le16_to_cpu(ctrl->wIndex); 1234 u8 intf = w_index & 0xFF; 1235 u16 w_value = le16_to_cpu(ctrl->wValue); 1236 u16 w_length = le16_to_cpu(ctrl->wLength); 1237 struct usb_function *f = NULL; 1238 u8 endp; 1239 1240 /* partial re-init of the response message; the function or the 1241 ┊* gadget might need to intercept e.g. a control-OUT completion 1242 ┊* when we delegate to it. 1243 ┊*/ 1244 req->zero = 0; 1245 req->complete = composite_setup_complete; 1246 req->length = 0; 1247 gadget->ep0->driver_data = cdev; 1248 1249 switch (ctrl->bRequest) { 1251 /* we handle all standard USB descriptors */ 1252 case USB_REQ_GET_DESCRIPTOR: 1253 if (ctrl->bRequestType != USB_DIR_IN) 1254 goto unknown; 1255 switch (w_value >> 8) { 1256 1257 case USB_DT_DEVICE: //設備描述符 1258 cdev->desc.bNumConfigurations = 1259 count_configs(cdev, USB_DT_DEVICE); 1260 cdev->desc.bMaxPacketSize0 = 1261 cdev->gadget->ep0->maxpacket; 1262 if (gadget_is_superspeed(gadget)) { 1263 if (gadget->speed >= USB_SPEED_SUPER) { 1264 cdev->desc.bcdUSB = cpu_to_le16(0x0300); 1265 cdev->desc.bMaxPacketSize0 = 9; 1266 } else { 1267 cdev->desc.bcdUSB = cpu_to_le16(0x0210); 1268 } 1269 } 1270 1271 value = min(w_length, (u16) sizeof cdev->desc); 1272 memcpy(req->buf, &cdev->desc, value); 1273 break; 1274 case USB_DT_DEVICE_QUALIFIER: //the structure is used by USB client drivers to retrieve a USB-defined device qualifier descriptor. 1275 if (!gadget_is_dualspeed(gadget) || 1276 ┊ gadget->speed >= USB_SPEED_SUPER) 1277 break; 1278 device_qual(cdev); 1279 value = min_t(int, w_length, 1280 sizeof(struct usb_qualifier_descriptor)); 1281 break; 1282 case USB_DT_OTHER_SPEED_CONFIG: 1283 if (!gadget_is_dualspeed(gadget) || 1284 ┊ gadget->speed >= USB_SPEED_SUPER) 1285 break; 1286 /* FALLTHROUGH */ 1287 case USB_DT_CONFIG: //配置描述符 1288 value = config_desc(cdev, w_value); 1289 if (value >= 0) 1290 value = min(w_length, (u16) value); 1291 break; 1292 case USB_DT_STRING: //字符串描述符 1293 value = get_string(cdev, req->buf, 1294 w_index, w_value & 0xff); 1295 if (value >= 0) 1296 value = min(w_length, (u16) value); 1297 break; 1298 case USB_DT_BOS: 1299 if (gadget_is_superspeed(gadget)) { 1300 value = bos_desc(cdev); 1301 value = min(w_length, (u16) value); 1302 } 1303 break; 1304 } 1305 break; 1306 1307 /* any number of configs can work */ 1308 case USB_REQ_SET_CONFIGURATION: 1309 if (ctrl->bRequestType != 0) 1310 goto unknown; 1311 if (gadget_is_otg(gadget)) { 1312 if (gadget->a_hnp_support) 1313 DBG(cdev, "HNP available\n"); 1314 else if (gadget->a_alt_hnp_support) 1315 DBG(cdev, "HNP on another port\n"); 1316 else 1317 VDBG(cdev, "HNP inactive\n"); 1318 } 1319 spin_lock(&cdev->lock); 1320 value = set_config(cdev, ctrl, w_value); 1321 spin_unlock(&cdev->lock); 1322 break; 1323 case USB_REQ_GET_CONFIGURATION: 1324 if (ctrl->bRequestType != USB_DIR_IN) 1325 goto unknown; 1326 if (cdev->config) 1327 *(u8 *)req->buf = cdev->config->bConfigurationValue; 1328 else 1329 *(u8 *)req->buf = 0; 1330 value = min(w_length, (u16) 1); 1331 break; 1333 /* function drivers must handle get/set altsetting; if there's 1334 ┊* no get() method, we know only altsetting zero works. 1335 ┊*/ 1336 case USB_REQ_SET_INTERFACE: //配置接口 1337 if (ctrl->bRequestType != USB_RECIP_INTERFACE) 1338 goto unknown; 1339 if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) 1340 break; 1341 f = cdev->config->interface[intf]; 1342 if (!f) 1343 break; 1344 if (w_value && !f->set_alt) 1345 break; 1346 value = f->set_alt(f, w_index, w_value); //設置當前接口爲第一個接口0,在上文中有說起該函數的做用 1347 if (value == USB_GADGET_DELAYED_STATUS) { 1348 DBG(cdev, 1349 ┊"%s: interface %d (%s) requested delayed status\n", 1350 __func__, intf, f->name); 1351 cdev->delayed_status++; 1352 DBG(cdev, "delayed_status count %d\n", 1353 cdev->delayed_status); 1354 } 1355 break; 1356 case USB_REQ_GET_INTERFACE: 1357 if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) 1358 goto unknown; 1359 if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) 1360 break; 1361 f = cdev->config->interface[intf]; 1356 case USB_REQ_GET_INTERFACE: 1357 if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) 1358 goto unknown; 1359 if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) 1360 break; 1361 f = cdev->config->interface[intf]; 1362 if (!f) 1363 break; 1364 /* lots of interfaces only need altsetting zero... */ 1365 value = f->get_alt ? f->get_alt(f, w_index) : 0; 1366 if (value < 0) 1367 break; 1368 *((u8 *)req->buf) = value; 1369 value = min(w_length, (u16) 1); 1370 break; 1371 1372 /* 1373 ┊* USB 3.0 additions: 1374 ┊* Function driver should handle get_status request. If such cb 1375 ┊* wasn't supplied we respond with default value = 0 1376 ┊* Note: function driver should supply such cb only for the first 1377 ┊* interface of the function 1378 ┊*/ 1379 case USB_REQ_GET_STATUS: 1380 if (!gadget_is_superspeed(gadget)) 1381 goto unknown; 1382 if (ctrl->bRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE)) 1383 goto unknown; 1384 value = 2; /* This is the length of the get_status reply */ 1384 value = 2; /* This is the length of the get_status reply */ 1385 put_unaligned_le16(0, req->buf); 1386 if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) 1387 break; 1388 f = cdev->config->interface[intf]; 1389 if (!f) 1390 break; 1391 status = f->get_status ? f->get_status(f) : 0; 1392 if (status < 0) 1393 break; 1394 put_unaligned_le16(status & 0x0000ffff, req->buf); 1395 break; 1396 /* 1397 ┊* Function drivers should handle SetFeature/ClearFeature 1398 ┊* (FUNCTION_SUSPEND) request. function_suspend cb should be supplied 1399 ┊* only for the first interface of the function 1400 ┊*/ 1401 case USB_REQ_CLEAR_FEATURE: 1402 case USB_REQ_SET_FEATURE: 1403 if (!gadget_is_superspeed(gadget)) 1404 goto unknown; 1405 if (ctrl->bRequestType != (USB_DIR_OUT | USB_RECIP_INTERFACE)) 1406 goto unknown; 1407 switch (w_value) { 1408 case USB_INTRF_FUNC_SUSPEND: 1409 if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) 1410 break; 1411 f = cdev->config->interface[intf]; 1412 if (!f) 1409 if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) 1410 break; 1411 f = cdev->config->interface[intf]; 1412 if (!f) 1413 break; 1414 value = 0; 1415 if (f->func_suspend) 1416 value = f->func_suspend(f, w_index >> 8); 1417 if (value < 0) { 1418 ERROR(cdev, 1419 ┊ ┊ "func_suspend() returned error %d\n", 1420 ┊ ┊ value); 1421 value = 0; 1422 } 1423 break; 1424 } 1425 break; 1426 default: 1427 unknown: //假若枚舉過程當中發送了沒法識別的請求。 1428 VDBG(cdev, 1429 "non-core control req%02x.%02x v%04x i%04x l%d\n", 1430 ctrl->bRequestType, ctrl->bRequest, 1431 w_value, w_index, w_length); 1432 1433 /* functions always handle their interfaces and endpoints... 1434 ┊* punt other recipients (other, WUSB, ...) to the current 1435 ┊* configuration code. 1436 ┊* 1437 ┊* REVISIT it could make sense to let the composite device 1435 ┊* configuration code. 1436 ┊* 1437 ┊* REVISIT it could make sense to let the composite device 1438 ┊* take such requests too, if that's ever needed: to work 1439 ┊* in config 0, etc. 1440 ┊*/ 1441 switch (ctrl->bRequestType & USB_RECIP_MASK) { 1442 case USB_RECIP_INTERFACE: 1443 if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) 1444 break; 1445 f = cdev->config->interface[intf]; 1446 break; 1447 1448 case USB_RECIP_ENDPOINT: 1449 endp = ((w_index & 0x80) >> 3) | (w_index & 0x0f); 1450 list_for_each_entry(f, &cdev->config->functions, list) { 1451 if (test_bit(endp, f->endpoints)) 1452 break; 1453 } 1454 if (&f->list == &cdev->config->functions) 1455 f = NULL; 1456 break; 1457 } 1458 1459 if (f && f->setup) 1460 value = f->setup(f, ctrl); //當時在分析該代碼時候,很不明白function中爲啥還設置setup函數,至少zero驅動中source sink只是簡單的處理了下。 1461 else { 1462 struct usb_configuration *c; 1463 1464 c = cdev->config; 1465 if (!c) 1466 goto done; 1467 1468 /* try current config's setup */ 1469 if (c->setup) { 1470 value = c->setup(c, ctrl); 1471 goto done; 1472 } 1473 1474 /* try the only function in the current config */ 1475 if (!list_is_singular(&c->functions)) 1476 goto done; 1477 f = list_first_entry(&c->functions, struct usb_function, 1478 ┊ ┊list); 1479 if (f->setup) 1480 value = f->setup(f, ctrl); 1481 } 1482 1483 goto done; 1484 } 1485 //其實在每個case語句裏面,都對req進行了填充。並調用發送函數usb_eq_queue,作好執行回饋函數。 1486 /* respond with data transfer before status phase? */ 1487 if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) { 1488 req->length = value; 1489 req->zero = value < w_length; 1490 value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);//將封裝好的數據,發送到udc指定的fifo中返回給主機,並調用回調函數composite_setup_complete 1491 if (value < 0) { 1492 DBG(cdev, "ep_queue --> %d\n", value); 1493 req->status = 0; 1494 composite_setup_complete(gadget->ep0, req);//complete響應函數。 1495 } 1496 } else if (value == USB_GADGET_DELAYED_STATUS && w_length != 0) { 1497 WARN(cdev, 1498 "%s: Delayed status not supported for w_length != 0", 1499 __func__); 1500 } 1501 1502 done: 1503 /* device either stalls (value < 0) or reports success */ 1504 if (value < 0) { 1505 printk("control error %d req%02x.%02x v%04x i%04x l%d\n", value, 1506 ctrl->bRequestType, ctrl->bRequest, 1507 w_value, w_index, w_length); 1508 } 1509 return value; 1510 }
usb_ep_queue實際調用的是udc中實現的queue函數。
1116 static struct usb_ep_ops omap_ep_ops = { 1117 .enable = omap_ep_enable, 1118 .disable = omap_ep_disable, 1119 1120 .alloc_request = omap_alloc_request, 1121 .free_request = omap_free_request, 1122 1123 .queue = omap_ep_queue,//該函數的做用主要是講req寫入
到對應的端點中的queue隊列中去。
1002 list_add_tail(&req->queue, &ep->queue);
下面好好分析下填充好了req後,是怎樣經過omap_ep_queue函數發送的。
omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) 869 { 870 struct omap_ep *ep = container_of(_ep, struct omap_ep, ep); 871 struct omap_req *req = container_of(_req, struct omap_req, req); 872 struct omap_udc *udc; 873 unsigned long flags; 874 int is_iso = 0; 875 876 /* catch various bogus parameters */ 877 if (!_req || !req->req.complete || !req->req.buf //毋庸置疑,爲了代碼的嚴謹性,對req進行相關斷定是必然的。 878 || !list_empty(&req->queue)) { 879 DBG("%s, bad params\n", __func__); 880 return -EINVAL; 881 } 882 if (!_ep || (!ep->ep.desc && ep->bEndpointAddress)) {//這個時候端點描述符顯得尤其重要。 883 DBG("%s, bad ep\n", __func__); 884 return -EINVAL; 885 } 886 if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) { 887 if (req->req.length > ep->ep.maxpacket) 888 return -EMSGSIZE; 889 is_iso = 1; 890 } 891 892 /* this isn't bogus, but OMAP DMA isn't the only hardware to 893 ┊* have a hard time with partial packet reads... reject it. 894 ┊*/ 895 if (use_dma 896 && ep->has_dma 897 && ep->bEndpointAddress != 0 898 && (ep->bEndpointAddress & USB_DIR_IN) == 0 899 && (req->req.length % ep->ep.maxpacket) != 0) { 900 DBG("%s, no partial packet OUT reads\n", __func__); 901 return -EMSGSIZE; 902 } 903 904 udc = ep->udc; //獲取ucd控制器實例,這個時候就是req和udc結合高潮來臨的節奏。 905 if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) 906 return -ESHUTDOWN; 907 908 if (use_dma && ep->has_dma)//dma支持嗎? 909 usb_gadget_map_request(&udc->gadget, &req->req, 909 usb_gadget_map_request(&udc->gadget, &req->req, 910 (ep->bEndpointAddress & USB_DIR_IN)); 911 912 VDBG("%s queue req %p, len %d buf %p\n", 913 ep->ep.name, _req, _req->length, _req->buf); 914 915 spin_lock_irqsave(&udc->lock, flags); 916 917 req->req.status = -EINPROGRESS; 918 req->req.actual = 0; 919 920 /* maybe kickstart non-iso i/o queues */ 921 if (is_iso) { 922 u16 w; 923 924 w = omap_readw(UDC_IRQ_EN); 925 w |= UDC_SOF_IE; 926 omap_writew(w, UDC_IRQ_EN); 927 } else if (list_empty(&ep->queue) && !ep->stopped && !ep->ackwait) { 928 int is_in; 929 930 if (ep->bEndpointAddress == 0) { //如果控制端點0 931 if (!udc->ep0_pending || !list_empty(&ep->queue)) { 932 spin_unlock_irqrestore(&udc->lock, flags); 933 return -EL2HLT; 934 } 935 936 /* empty DATA stage? */ 937 is_in = udc->ep0_in; 938 if (!req->req.length) { //對於端點0,而且或者req數據長度爲0,顯然,不用進行回覆,直接調用done函數表示完成傳輸。 939 940 /* chip became CONFIGURED or ADDRESSED 941 ┊* earlier; drivers may already have queued 942 ┊* requests to non-control endpoints 943 ┊*/ 944 if (udc->ep0_set_config) { 945 u16 irq_en = omap_readw(UDC_IRQ_EN); 946 947 irq_en |= UDC_DS_CHG_IE | UDC_EP0_IE; 948 if (!udc->ep0_reset_config) 949 irq_en |= UDC_EPN_RX_IE 950 | UDC_EPN_TX_IE; 951 omap_writew(irq_en, UDC_IRQ_EN); //是能udc中斷 952 } 953 954 /* STATUS for zero length DATA stages is 955 ┊* always an IN ... even for IN transfers, 956 ┊* a weird case which seem to stall OMAP. 957 ┊*/ 958 omap_writew(UDC_EP_SEL | UDC_EP_DIR, 959 UDC_EP_NUM); 960 omap_writew(UDC_CLR_EP, UDC_CTRL); 961 omap_writew(UDC_SET_FIFO_EN, UDC_CTRL);//設置fifo使能 962 omap_writew(UDC_EP_DIR, UDC_EP_NUM);//配置端點放向和號 963 964 /* cleanup */ 965 udc->ep0_pending = 0; //將控制端點0設置爲非掛起狀態,即空閒狀態。 966 done(ep, req, 0);967 req = NULL; 968 969 /* non-empty DATA stage */ 970 } else if (is_in) { 971 omap_writew(UDC_EP_SEL | UDC_EP_DIR, 972 UDC_EP_NUM); 973 } else { 974 if (udc->ep0_setup) //若端點處理創建狀態則說明該端點中數據還沒發送完成,即須要發送請求。則將req加入控制器隊列queue中。 975 goto irq_wait; 976 omap_writew(UDC_EP_SEL, UDC_EP_NUM); 977 } 978 } else { 979 is_in = ep->bEndpointAddress & USB_DIR_IN; 980 if (!ep->has_dma) 981 use_ep(ep, UDC_EP_SEL); 982 /* if ISO: SOF IRQs must be enabled/disabled! */ 983 } 984 985 if (ep->has_dma) 986 (is_in ? next_in_dma : next_out_dma)(ep, req); 987 else if (req) { 988 if ((is_in ? write_fifo : read_fifo)(ep, req) == 1) //如果in則調用write_fifo,將req寫入隊列中,如果out,則調用read函數,並釋放req 989 req = NULL; 990 deselect_ep(); 991 if (!is_in) { 992 omap_writew(UDC_SET_FIFO_EN, UDC_CTRL); 993 ep->ackwait = 1 + ep->double_buf; 994 } 995 /* IN: 6 wait states before it'll tx */ 996 } 997 } 998 999 irq_wait: 1000 /* irq handler advances the queue */ 1001 if (req != NULL) 1002 list_add_tail(&req->queue, &ep->queue);//將usb加入隊列中,等待中斷處理,處理完後就調用中斷回調函數,done 1003 spin_unlock_irqrestore(&udc->lock, flags); 1004 1005 return 0; 1006 }
自此,枚舉過程已經講完,若是成功的話,會返回0值,小於0值,那就得調用composite_setup_complete,代表枚舉過程失敗了。
講完枚舉過程,這裏還講下usb_request的傳輸過程。當時開發項目時,主要用到loopback功能,主要是對ep_in和out的包進行攔截,後並進行處理。
looback功能很按照字面意思很簡單,就是普通的回覆,即收到的req轉給發出的req。
host和gadge之間的通訊主要依靠中斷,在gadget端,進行數據通訊時,收到bulk處理指令後都會調用各自端點實現的complete函數,對於loopback來講,關鍵的處理函數以下:
此處針對omap_udc.c控制器簡單的介紹下:
omap_udc_pio_irq-->write_fifo/read_fifo--->done->req.complete; //看起來很簡單,實際上是花費筆者較長時間才弄明白的。
246 static void loopback_complete(struct usb_ep *ep, struct usb_request *req) 247 { 248 struct f_loopback *loop = ep->driver_data; 249 struct usb_composite_dev *cdev = loop->function.config->cdev; 250 int status = req->status; 251 252 switch (status) { 253 254 case 0: /* normal completion? */ 255 if (ep == loop->out_ep) { //若是host端發送過來的out_ep,則須要將包轉發給ep_in端點。 256 /* loop this OUT packet back IN to the host */ 257 req->zero = (req->actual < req->length); 258 req->length = req->actual; 259 status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC);//轉發很簡單,直接把收到的轉到另一個端點便可,對於須要經過loopback功能
//將req->buf中的包進行某些處理的,能夠增長字符操做接口,對buf進行處理後再發送
//給對應得端點。 260 if (status == 0) 261 return; 262 263 /* "should never get here" */ 264 ERROR(cdev, "can't loop %s to %s: %d\n", 265 ep->name, loop->in_ep->name, 266 status); 267 } 268 269 /* queue the buffer for some later OUT packet */ 270 req->length = buflen; 271 status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC); //很顯然,若是是in_ep端點的話,須要將out_ep中包發出。 272 if (status == 0) 273 return; 274 275 /* "should never get here" */ 276 /* FALLTHROUGH */ 277 278 default: 279 ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name, 280 status, req->actual, req->length); 281 /* FALLTHROUGH */ 282 283 /* NOTE: since this driver doesn't maintain an explicit record 284 ┊* of requests it submitted (just maintains qlen count), we 285 ┊* rely on the hardware driver to clean up on disconnect or 286 ┊* endpoint disable. 287 ┊*/ 288 case -ECONNABORTED: /* hardware forced ep reset */ 289 case -ECONNRESET: /* request dequeued */ 290 case -ESHUTDOWN: /* disconnect from host */ 291 free_ep_req(ep, req); 292 return; 293 } 294 }