说明:本分析基于mstar801平台Linux2.6.35.11内核,其他内核版本仅供参考。
一、程序在内核中的位置
1.usb host做为pci总线下的一个设备存在(嵌入式系统中有可能也会直接挂在CPU上);这部分驱动由厂家实现,本分析以mstar为例。
2.USB总线驱动
kernel/drivers/usb/core/driver.c
- EXPORT_SYMBOL_GPL(usb_register_driver);
- EXPORT_SYMBOL_GPL(usb_deregister);
- EXPORT_SYMBOL_GPL(usb_register_device_driver);
- EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
- structbus_typeusb_bus_type={
- .name="usb",
- .match=usb_device_match,
- .uevent=usb_uevent,
- };
- staticint__initusb_init(void){
- bus_register(&usb_bus_type);
- usb_register_device_driver(&usb_generic_driver,THIS_MODULE);
- }
kernel/drivers/media/video/uvc/uvc_driver.c
- usb_register(&uvc_driver.driver);
二、所有总线、设备和驱动的注册函数
1.设备注册
kernel/drivers/base/core.c
- intdevice_register(structdevice*dev){
- device_initialize(dev);
- returndevice_add(dev);
- }
- intdevice_add(structdevice*dev){//所有的设备注册都需要走这里!!!!!!
- error=bus_add_device(dev);
- kobject_uevent(&dev->kobj,KOBJ_ADD);//上报uevent事件
- bus_probe_device(dev);//添加到总线
- }
kernel/drivers/base/driver.c
- intdriver_register(structdevice_driver*drv){//所有的驱动注册都要走这里!!!!!!!
- ret=bus_add_driver(drv);//添加到总线
- }
kernel/drivers/base/bus.c
- intbus_register(structbus_type*bus);
三、具体分析
情况一:当插入USB设备时USB host会检测到这一事件;然后通过USB core去匹配驱动。
当守护程序第一次运行(特殊USB设备USB hub就是这种情况)或usb port上状态发生变化(其余所有USB设备插入都是这种情况)守护进程被唤醒时,会运行hub_events函数、USB的枚举过程就是由它完成。
1.USB host部分代码
说明:从硬件层面来看,ehci主控器从PCI总线桥接,是PCI驱动程序实例。
kernel/drivers/usb/host/ehci-hcd.c
- module_init(ehci_hcd_init);
- #definePCI_DRIVERehci_pci_driver//利用pci中断
- #definePLATFORM_DRIVERehci_hcd_mstar_driver//利用定时器轮询
- staticint__initehci_hcd_init(void){
- #ifdefPLATFORM_DRIVER
- platform_driver_register(&PLATFORM_DRIVER);
- #endif
- #ifdefPCI_DRIVER
- pci_register_driver(&PCI_DRIVER);
- #endif
- }
==============================================
定时器轮询:
kernel/drivers/usb/host/ehci-mstar.c
- staticstructplatform_driverehci_hcd_mstar_driver={
- .probe=ehci_hcd_mstar_drv_probe,
- };
- staticintehci_hcd_mstar_drv_probe(structplatform_device*pdev){
- usb_ehci_mstar_probe(&ehci_mstar_hc_driver,&hcd,pdev);
- }
- intusb_ehci_mstar_probe(conststructhc_driver*driver,structusb_hcd**hcd_out,structplatform_device*dev){
- usb_create_hcd(driver,&dev->dev,"mstar");
- }
- structusb_hcd*usb_create_hcd(conststructhc_driver*driver,structdevice*dev,constchar*bus_name){
- returnusb_create_shared_hcd(driver,dev,bus_name,NULL);
- }
- structusb_hcd*usb_create_shared_hcd(conststructhc_driver*driver,structdevice*dev,constchar*bus_name,structusb_hcd*primary_hcd){
- init_timer(&hcd->rh_timer);
- hcd->rh_timer.function=rh_timer_func;
- }
- staticvoidrh_timer_func(unsignedlong_hcd){
- usb_hcd_poll_rh_status((structusb_hcd*)_hcd);
- }
- voidusb_hcd_poll_rh_status(structusb_hcd*hcd){
- hcd->driver->hub_status_data(hcd,buffer);
- usb_hcd_giveback_urb(hcd,urb,0);
- }
===================
当有pci中断发生后:
kernel/drivers/usb/host/ehci-pci.c
- staticstructpci_driverehci_pci_driver={
- .id_table=pci_ids,
- }
- staticconststructpci_device_idpci_ids[]={{
- .driver_data=(unsignedlong)&ehci_pci_hc_driver,
- }
- }
- staticconststructhc_driverehci_pci_hc_driver={
- .irq=ehci_irq,//中断
- .hub_status_data=ehci_hub_status_data,
- .urb_enqueue=ehci_urb_enqueue,
- .urb_dequeue=ehci_urb_dequeue,
- }
- staticirqreturn_tehci_irq(structusb_hcd*hcd){
- usb_hcd_poll_rh_status(hcd);
- }
kernel/drivers/usb/core/hcd.c
- voidusb_hcd_poll_rh_status(structusb_hcd*hcd){
- hcd->driver->hub_status_data(hcd,buffer);
- usb_hcd_giveback_urb(hcd,urb,0);
- }
kernel/drivers/usb/host/ehci-hub.c
- staticintehci_hub_status_data(structusb_hcd*hcd,char*buf){
- }
=====================================================================
从以上分析可以看出;不论是定时器轮询还是pci中断,最终都会执行usb_hcd_giveback_urb函数:
kernel/drivers/usb/core/hcd.c
- voidusb_hcd_giveback_urb(structusb_hcd*hcd,structurb*urb,intstatus){
- urb->complete(urb);
- }
而上处urv->complete函数其实就是如下的hub_irq函数,后边会分析:
kernel/drivers/usb/core/hub.c
- staticvoidhub_irq(structurb*urb){
- kick_khubd(hub);
- }
2.USB core即USB总线部分代码——可以看到hub是第一个USB设备而且与USB总线密切相关
kernel/drivers/usb/core/usb.c
- subsys_initcall(usb_init);
- structbus_typeusb_bus_type={
- .name="usb",
- .match=usb_device_match,
- .uevent=usb_uevent,
- };
- staticint__initusb_init(void){
- bus_register(&usb_bus_type);
- usb_register_device_driver(&usb_generic_driver,THIS_MODULE);//USB设备驱动,在没有roothub时使用
- usb_hub_init();
- }
- staticstructusb_driverhub_driver={
- .name="hub",
- .probe=hub_probe,
- };
- intusb_hub_init(void){
- usb_register(&hub_driver);//USB设备驱动,第一个USB设备—roothub
- kthread_run(hub_thread,NULL,"khubd");
- }
=====================================
插句话:下边就是之前我们说的urv->complete被赋为hub_irq函数的过程;
这里说明一下:hub的探测函数的执行是在守护线程第一次运行时的情况;为什么不需要USB总线轮询后或PCI总线中断后就执行?我们会在后边hub创建线程处看到。
- staticinthub_probe(structusb_interface*intf,conststructusb_device_id*id){
- hub_configure(hub,endpoint);
- }
- staticinthub_configure(structusb_hub*hub,structusb_endpoint_descriptor*endpoint){
- usb_fill_int_urb(hub->urb,hdev,pipe,*hub->buffer,maxp,hub_irq,hub,endpoint->bInterval);
- }
- staticinlinevoidusb_fill_int_urb(structurb*urb,structusb_device*dev,unsignedintpipe,void*transfer_buffer,intbuffer_length,
- usb_complete_tcomplete_fn,void*context,intinterval){
- urb->complete=complete_fn;
- }
kernel/drivers/usb/core/hub.c
这里特别强调:hub设备是第一个USB设备,也是必须的USB设备;它不需要通过USB总线定时器轮询或PCI总线中断来触发。从下边代码也可以看出,在执行第一次hub_events之后(hub驱动的probe函数被执行、urv->complete被赋值hub_irq),该线程才会睡眠!
- staticinthub_thread(void*__unused){
- do{
- hub_events();//重要!最核心部分
- wait_event_freezable(khubd_wait,!list_empty(&hub_event_list)||kthread_should_stop());
- }while(!kthread_should_stop()||!list_empty(&hub_event_list));
- }
- //内核守护线程khubd,它被kick_khubd唤醒(当prot上状态发生变化时,USBhost会调用usb_hcd_poll_rh_status去查询usbroothubport状态,并调用hub中的interrupturb的回调函数hub_irq,最终去唤醒usb内核守护线程)、通过自身调用wait_event_freezable进入睡眠。
- staticvoidhub_events(void){
- if(connect_change)hub_port_connect_change(hub,i,portstatus,portchange);
- }
- staticvoidhub_port_connect_change(structusb_hub*hub,intport1,u16portstatus,u16portchange){
- status=hub_port_init(hub,udev,port1,i);
- status=usb_new_device(udev);
- }
- intusb_new_device(structusb_device*udev){
- err=device_add(&udev->dev);
- (void)usb_create_ep_devs(&udev->dev,&udev->ep0,udev);
- /*
- kernel/drivers/usb/core/endpoint.c
- intusb_create_ep_devs(structdevice*parent,structusb_host_endpoint*endpoint,structusb_device*udev){
- device_register(&ep_dev->dev);
- }
- */
- }
- intdevice_add(structdevice*dev){//所有的设备注册都需要走这里!!!!!!
- error=bus_add_device(dev);
- kobject_uevent(&dev->kobj,KOBJ_ADD);//上报uevent事件
- bus_probe_device(dev);
- }
- voidbus_probe_device(structdevice*dev){
- ret=device_attach(dev);
- }
- intdevice_attach(structdevice*dev){
- ret=bus_for_each_drv(dev->bus,NULL,dev,__device_attach);
- }
- intbus_for_each_drv(structbus_type*bus,structdevice_driver*start,void*data,int(*fn)(structdevice_driver*,void*)){
- while((drv=next_driver(&i))&&!error)
- error=fn(drv,data);
- }
- staticint__device_attach(structdevice_driver*drv,void*data){
- if(!driver_match_device(drv,dev))
- return0;
- /*
- kernel/drivers/base/base.h
- staticinlineintdriver_match_device(structdevice_driver*drv,structdevice*dev){
- returndrv->bus->match?drv->bus->match(dev,drv):1;
- }
- kernel/drivers/usb/core/driver.c
- staticintusb_device_match(structdevice*dev,structdevice_driver*drv){
- intf=to_usb_interface(dev);
- usb_drv=to_usb_driver(drv);
- if(id)return1;
- id=usb_match_dynamic_id(intf,usb_drv);
- if(id)return1;
- return0;
- }
- */
- returndriver_probe_device(drv,dev);
- }
- intdriver_probe_device(structdevice_driver*drv,structdevice*dev){
- ret=really_probe(dev,drv);
- }
- staticintreally_probe(structdevice*dev,structdevice_driver*drv){
- dev->driver=drv;
- if(dev->bus->probe){
- ret=dev->bus->probe(dev);
- if(ret)gotoprobe_failed;
- }elseif(drv->probe){
- ret=drv->probe(dev);
- if(ret)gotoprobe_failed;
- }
- }
kernel/drivers/media/video/uvc/uvc_driver.c
- structuvc_driveruvc_driver={
- .driver={
- .name="uvcvideo",
- .probe=uvc_probe,
- .disconnect=uvc_disconnect,
- .suspend=uvc_suspend,
- .resume=uvc_resume,
- .reset_resume=uvc_reset_resume,
- .id_table=uvc_ids,
- .supports_autosuspend=1,
- },
- };
- module_init(uvc_init);
- staticint__inituvc_init(void){
- result=usb_register(&uvc_driver.driver);
- }
- staticinlineintusb_register(structusb_driver*driver){
- returnusb_register_driver(driver,THIS_MODULE,KBUILD_MODNAME);
- }
- intusb_register_driver(structusb_driver*new_driver,structmodule*owner,constchar*mod_name){
- retval=driver_register(&new_driver->drvwrap.driver);
- }
- intdriver_register(structdevice_driver*drv){//所有的驱动注册都要走这里!!!!!!!
- ret=bus_add_driver(drv);
- }
- intbus_add_driver(structdevice_driver*drv){
- error=driver_attach(drv);
- kobject_uevent(&priv->kobj,KOBJ_ADD);
- }
- intdriver_attach(structdevice_driver*drv){
- returnbus_for_each_dev(drv->bus,NULL,drv,__driver_attach);
- }
- intbus_for_each_dev(structbus_type*bus,structdevice*start,void*data,int(*fn)(structdevice*,void*)){
- while((dev=next_device(&i))&&!error)error=fn(dev,data);
- }
- staticint__driver_attach(structdevice*dev,void*data){
- if(!driver_match_device(drv,dev))return0;
- /*
- kernel/drivers/base/base.h
- staticinlineintdriver_match_device(structdevice_driver*drv,structdevice*dev){
- returndrv->bus->match?drv->bus->match(dev,drv):1;
- }
- kernel/drivers/usb/core/driver.c
- staticintusb_device_match(structdevice*dev,structdevice_driver*drv){
- intf=to_usb_interface(dev);
- usb_drv=to_usb_driver(drv);
- if(id)return1;
- id=usb_match_dynamic_id(intf,usb_drv);
- if(id)return1;
- return0;
- }
- */
- if(!dev->driver)driver_probe_device(drv,dev);
- }
- intdriver_probe_device(structdevice_driver*drv,structdevice*dev){
- ret=really_probe(dev,drv);
- }
- staticintreally_probe(structdevice*dev,structdevice_driver*drv){
- dev->driver=drv;
- if(dev->bus->probe){
- ret=dev->bus->probe(dev);
- if(ret)gotoprobe_failed;
- }elseif(drv->probe){
- ret=drv->probe(dev);
- if(ret)gotoprobe_failed;
- }
- }
3.总结
经过分析,总结:
(1).当总线上插入设备、总线会调用设备注册函数device_add/device_register;
(2).当insmod设备驱动、module_init函数里边一定有driver_register;
(3).通过上边分析,如上两个函数最终都会调用到总线驱动的match函数、进行匹配;如USB的总线match函数如下:
kernel/drivers/usb/core/driver.c
- structbus_typeusb_bus_type={
- .name="usb",
- .match=usb_device_match,
- .uevent=usb_uevent,
- .pm=&usb_bus_pm_ops,
- };
- staticintusb_device_match(structdevice*dev,structdevice_driver*drv)
- {
- /*devicesandinterfacesarehandledseparately*/
- if(is_usb_device(dev)){
- /*interfacedriversnevermatchdevices*/
- if(!is_usb_device_driver(drv))
- return0;
- /*TODO:Addrealmatchingcode*/
- return1;
- }elseif(is_usb_interface(dev)){
- structusb_interface*intf;
- structusb_driver*usb_drv;
- conststructusb_device_id*id;
- /*devicedriversnevermatchinterfaces*/
- if(is_usb_device_driver(drv))
- return0;
- intf=to_usb_interface(dev);
- usb_drv=to_usb_driver(drv);
- id=usb_match_id(intf,usb_drv->id_table);//USB是匹配驱动中的id_table
- if(id)
- return1;
- id=usb_match_dynamic_id(intf,usb_drv);
- if(id)
- return1;
- }
- return0;
- }
下边也看看UVC Camera驱动的id_table:
kernel/drivers/media/video/uvc/uvc_driver.c
- structuvc_driveruvc_driver={
- .driver={
- .name="uvcvideo",
- .probe=uvc_probe,
- .disconnect=uvc_disconnect,
- .suspend=uvc_suspend,
- .resume=uvc_resume,
- .reset_resume=uvc_reset_resume,
- .id_table=uvc_ids,
- .supports_autosuspend=1,
- },
- };
- staticstructusb_device_iduvc_ids[]={
- /*MicrosoftLifecamNX-6000*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x045e,
- .idProduct=0x00f8,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_PROBE_MINMAX},
- /*MicrosoftLifecamVX-7000*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x045e,
- .idProduct=0x0723,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_PROBE_MINMAX},
- /*LogitechQuickcamFusion*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x046d,
- .idProduct=0x08c1,
- .bInterfaceClass=USB_CLASS_VENDOR_SPEC,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0},
- /*LogitechQuickcamOrbitMP*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x046d,
- .idProduct=0x08c2,
- .bInterfaceClass=USB_CLASS_VENDOR_SPEC,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0},
- /*LogitechQuickcamProforNotebook*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x046d,
- .idProduct=0x08c3,
- .bInterfaceClass=USB_CLASS_VENDOR_SPEC,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0},
- /*LogitechQuickcamPro5000*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x046d,
- .idProduct=0x08c5,
- .bInterfaceClass=USB_CLASS_VENDOR_SPEC,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0},
- /*LogitechQuickcamOEMDellNotebook*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x046d,
- .idProduct=0x08c6,
- .bInterfaceClass=USB_CLASS_VENDOR_SPEC,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0},
- /*LogitechQuickcamOEMCiscoVTCameraII*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x046d,
- .idProduct=0x08c7,
- .bInterfaceClass=USB_CLASS_VENDOR_SPEC,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0},
- /*AppleBuilt-IniSight*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x05ac,
- .idProduct=0x8501,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_PROBE_MINMAX
- |UVC_QUIRK_BUILTIN_ISIGHT},
- /*GenesysLogicUSB2.0PCCamera*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x05e3,
- .idProduct=0x0505,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_STREAM_NO_FID},
- /*MT6227*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x0e8d,
- .idProduct=0x0004,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_PROBE_MINMAX},
- /*Syntek(HPSpartan)*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x174f,
- .idProduct=0x5212,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_STREAM_NO_FID},
- /*Syntek(SamsungQ310)*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x174f,
- .idProduct=0x5931,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_STREAM_NO_FID},
- /*AsusF9SG*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x174f,
- .idProduct=0x8a31,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_STREAM_NO_FID},
- /*Syntek(AsusU3S)*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x174f,
- .idProduct=0x8a33,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_STREAM_NO_FID},
- /*LenovoThinkpadSL500*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x17ef,
- .idProduct=0x480b,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_STREAM_NO_FID},
- /*EcammPicoiMage*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x18cd,
- .idProduct=0xcafe,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_PROBE_EXTRAFIELDS},
- /*BodelinProScopeHR*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_DEV_HI
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x19ab,
- .idProduct=0x1000,
- .bcdDevice_hi=0x0126,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_STATUS_INTERVAL},
- /*SiGmaMicroUSBWebCamera*/
- {.match_flags=USB_DEVICE_ID_MATCH_DEVICE
- |USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor=0x1c4f,
- .idProduct=0x3000,
- .bInterfaceClass=USB_CLASS_VIDEO,
- .bInterfaceSubClass=1,
- .bInterfaceProtocol=0,
- .driver_info=UVC_QUIRK_PROBE_MINMAX
- |UVC_QUIRK_IGNORE_SELECTOR_UNIT
- |UVC_QUIRK_PRUNE_CONTROLS},
- /*GenericUSBVideoClass*/
- {USB_INTERFACE_INFO(USB_CLASS_VIDEO,1,0)},
- {}
- };
三、usb相关结构说明
1.设备描述符
- structusb_device_descriptor{
- __u8bLength;--描述符长度
- __u8bDescriptorType;--描述符类型:设备描述符0x01
- __le16bcdUSB;--usb规范版本号
- __u8bDeviceClass;--类代码
- __u8bDeviceSubClass;--子类代码
- __u8bDeviceProtocol;--协议代码
- __u8bMaxPacketSize0;--端点0支持最大数
- __le16idVendor;--供应商ID
- __le16idProduct;--产品ID
- __le16bcdDevice;--设备版本号
- __u8iManufacturer;--供应商字符串描述符的索引值
- __u8iProduct;--产品字符串描述符的索引值
- __u8iSerialNumber;--设备序列号
- __u8bNumConfigurations;--所支持的配置数
- }__attribute__((packed));--结构体字符类型对齐
2.配置描述符
- structusb_config_descriptor{
- __u8bLength;--描述符长度
- __u8bDescriptorType;--描述符类型
- __le16wTotalLength;--配置信息的总长度
- __u8bNumInterfaces;--所支持的接口数
- __u8bConfigurationValue;--配置值
- __u8iConfiguration;--字符串描述符的索引值
- __u8bmAttributes;--配置特征
- __u8bMaxPower;--所需最大的总线电流
- }__attribute__((packed));
- structusb_interface_descriptor{
- __u8bLength;
- __u8bDescriptorType;
- __u8bInterfaceNumber;--接口编号
- __u8bAlternateSetting;--备用接口标号
- __u8bNumEndpoints;--接口数目
- __u8bInterfaceClass;--接口类型
- __u8bInterfaceSubClass;--接口子类型
- __u8bInterfaceProtocol;--接口所用协议
- __u8iInterface;--接口索引字符串数值
- }__attribute__((packed));
- structusb_endpoint_descriptor{
- __u8bLength;
- __u8bDescriptorType;
- __u8bEndpointAddress;--端点号包括传输方向
- __u8bmAttributes;--端点属性
- __le16wMaxPacketSize;--最大数据包长度
- __u8bInterval;--访问间隔
- __u8bRefresh;
- __u8bSynchAddress;
- }__attribute__((packed));
usb总线驱动中对于设备和设备驱动的匹配函数,其实就是上述1和3的匹配过程
见:kernel/drivers/usb/core/driver.c中usb_device_match函数,这部分可以进一步分析;在此、我不再分析。
大致会匹配设备所属类(Input设备?Camera设备?Audio设备?或显示设备等)和VID、PID。
五、urb数据传输分析
未完待续