USB驅動框架分析


轉載於 :http://blog.csdn.net/xuao20060793/article/details/46530481

本文主要分析usb框架的主要數據結構,usb驅動框架的初始化,usb系統模型的建立過程。先貼一張網上找來的圖,很清晰很詳細。

上圖濃縮了usb設備模型的建立流程,再次感謝網上前輩的經驗總結。下面以文字總結這個過程:

(1). usb主機控制器驅動的probe過程,分配usb_hcd,然后添加到系統中,一個主控制器對應一條usb總線,一個主控制器綁定着一個root hub,一個root hub對應於一個usb_device,然后注冊此root  hub,主要是調用usb_new_device。每個usb設備(usb_device)有一種或多種配置,每種配置有一個或多個接口,一個接口有一種或多種設置,一種設置有一個或多個端點。為了獲取並解析這些描述符,usb_new_device調用usb_configure_device,然后將設備添加到內核。每個usb設備都有一個控制端點。它通常用於配置設備,獲取設備信息,發送命令到設備,或者獲取設備的狀態報告,usb_new_device中調用了函數usb_create_ep_devs。

 

(2). 當root hub這個usb_device添加到系統中時,系統中也有一個usb_device_driver(注意,不是usb_driver),一個是對應usb設備,一個對應usb接口。匹配上之后就會調用generic_probe,在這個函數里面調用usb_choose_configuration為設備選擇一個合理的配置,到此就可以用選定配置下的所有描述符進行設備配置了。函數usb_set_configuration就是完成此項功能。在函數usb_set_configuration中將設備的所有接口都添加到內核device_add(&intf->dev)。這些接口設備的總線類型也是usb_bus_type,不過設備類型為usb_if_device_type。

 

(3). 接口添加到系統中了,當然要匹配接口驅動。恰好系統中有一個usb_driver為hub_driver,它是為hub接口准備的。接口又分為hub的接口和usb設備的接口。如果是設備的接口,如果匹配上了后就調用probe函數,做相應的初始化、設備模型建立等工作,例如usb storage驅動,后面會有介紹。如果是hub的接口,就調用hub_probe。

1. usb驅動框架的數據結構

 

[cpp] view plain copy
 
struct usb_device {  
    int     devnum; //usb設備在一條usb總線上的編號  
    char        devpath[16];    //路徑字符串  
    u32     route;  
    enum usb_device_state   state;  //狀態  
    enum usb_device_speed   speed;  //速度  
  
    struct usb_tt   *tt;    //高低速之間的數據轉換  
    int     ttport;  
  
    unsigned int toggle[2]; //每一位表示每個端點當前發送或接受的是DATA0還是DATA1  
  
    struct usb_device *parent;  //父usb設備  
    struct usb_bus *bus;    //設備所在的那條總線  
    struct usb_host_endpoint ep0;   //端點0,比較特殊  
  
    struct device dev;  //內嵌的device結構  
  
    struct usb_device_descriptor descriptor;    //設備描述符  
    struct usb_host_config *config; //usb設備的配置數組  
  
    struct usb_host_config *actconfig;  //usb設備的當前激活配置  
    struct usb_host_endpoint *ep_in[16];    //16個in端點  
    struct usb_host_endpoint *ep_out[16];   //16個out端點  
  
    char **rawdescriptors;  //指針數組,指向GET_DESCRIPTOR請求獲得的配置描述符的結果  
  
    unsigned short bus_mA;  
    u8 portnum; //端口號  
    u8 level;   //層次  
  
    unsigned can_submit:1;  
    unsigned persist_enabled:1;  
    unsigned have_langid:1;  
    unsigned authorized:1;  
    unsigned authenticated:1;  
    unsigned wusb:1;  
    int string_langid;  
  
    /* static strings from the device */  
    char *product;  
    char *manufacturer;  
    char *serial;  
  
    struct list_head filelist;  
#ifdef CONFIG_USB_DEVICE_CLASS  
    struct device *usb_classdev;    //類設備  
#endif  
#ifdef CONFIG_USB_DEVICEFS  
    struct dentry *usbfs_dentry;    //usbfs相關的目錄項  
#endif  
  
    int maxchild;   //Hub的端口數  
    struct usb_device *children[USB_MAXCHILDREN];   //子usb設備  
  
    u32 quirks;  
    atomic_t urbnum;  
  
    unsigned long active_duration;  
  
#ifdef CONFIG_PM  
    unsigned long connect_time;  
  
    unsigned do_remote_wakeup:1;  
    unsigned reset_resume:1;  
#endif  
    struct wusb_dev *wusb_dev;  
    int slot_id;  
};  
再來看下usb_device_descriptor

 

 

[cpp] view plain copy
 
struct usb_device_descriptor {  
    __u8  bLength;  //長度  
    __u8  bDescriptorType;  //描述符類型  
  
    __le16 bcdUSB;  //usb spec 的版本號  
    __u8  bDeviceClass; //設備的類  
    __u8  bDeviceSubClass;  //設備的子類  
    __u8  bDeviceProtocol;  //設備的協議  
    __u8  bMaxPacketSize0;  //端口0一次可以處理的最大字節數  
    __le16 idVendor;    //廠商ID  
    __le16 idProduct;   //產品ID  
    __le16 bcdDevice;   //設備的版本號      
    __u8  iManufacturer;    //廠商字符串對應的索引  
    __u8  iProduct; //產品字符串對應的索引  
    __u8  iSerialNumber;    //產品序列號對應的索引  
    __u8  bNumConfigurations;   //當前速度下的配置個數  
} __attribute__ ((packed));  
[cpp] view plain copy
 
struct usb_host_config {  
    struct usb_config_descriptor    desc;   //usb配置描述符  
  
    char *string;       /* iConfiguration string, if present */  
  
    /* List of any Interface Association Descriptors in this 
     * configuration. */  
    struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];  
  
    /* the interfaces associated with this configuration, 
     * stored in no particular order */  
    struct usb_interface *interface[USB_MAXINTERFACES]; //該配置包含的接口  
  
    /* Interface information available even when this is not the 
     * active configuration */  
    struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];  
  
    unsigned char *extra;   /* Extra descriptors */  
    int extralen;  
};  
[cpp] view plain copy
 
struct usb_config_descriptor {  
    __u8  bLength;  
    __u8  bDescriptorType;  
  
    __le16 wTotalLength;  
    __u8  bNumInterfaces;  
    __u8  bConfigurationValue;  
    __u8  iConfiguration;  
    __u8  bmAttributes;  
    __u8  bMaxPower;  
} __attribute__ ((packed));  
[cpp] view plain copy
 
struct usb_interface {  
    /* array of alternate settings for this interface, 
     * stored in no particular order */  
    struct usb_host_interface *altsetting;  //該接口的設置數組  
  
    struct usb_host_interface *cur_altsetting;  /* the currently 
                     * active alternate setting */  //該接口的當前設置  
    unsigned num_altsetting;    /* number of alternate settings */  
  
    /* If there is an interface association descriptor then it will list 
     * the associated interfaces */  
    struct usb_interface_assoc_descriptor *intf_assoc;  
  
    int minor;          /* minor number this interface is 
                     * bound to */  
    enum usb_interface_condition condition;     /* state of binding */  
    unsigned sysfs_files_created:1; /* the sysfs attributes exist */  
    unsigned ep_devs_created:1; /* endpoint "devices" exist */  
    unsigned unregistering:1;   /* unregistration is in progress */  
    unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */  
    unsigned needs_altsetting0:1;   /* switch to altsetting 0 is pending */  
    unsigned needs_binding:1;   /* needs delayed unbind/rebind */  
    unsigned reset_running:1;  
    unsigned resetting_device:1;    /* true: bandwidth alloc after reset */  
  
    struct device dev;      /* interface specific device info */  
    struct device *usb_dev;  
    atomic_t pm_usage_cnt;      /* usage counter for autosuspend */  
    struct work_struct reset_ws;    /* for resets in atomic context */  
};  
[cpp] view plain copy
 
struct usb_host_interface {  
    struct usb_interface_descriptor desc;   //接口描述符  
  
    /* array of desc.bNumEndpoint endpoints associated with this 
     * interface setting.  these will be in no particular order. 
     */  
    struct usb_host_endpoint *endpoint; //該設置用到的端點數組  
  
    char *string;       /* iInterface string, if present */  
    unsigned char *extra;   /* Extra descriptors */  
    int extralen;  
};  
[cpp] view plain copy
 
struct usb_interface_descriptor {  
    __u8  bLength;  
    __u8  bDescriptorType;  
  
    __u8  bInterfaceNumber;  
    __u8  bAlternateSetting;  
    __u8  bNumEndpoints;  
    __u8  bInterfaceClass;  
    __u8  bInterfaceSubClass;  
    __u8  bInterfaceProtocol;  
    __u8  iInterface;  
} __attribute__ ((packed));  
[cpp] view plain copy
 
struct usb_host_endpoint {  
    struct usb_endpoint_descriptor      desc;   //端點描述符  
    struct usb_ss_ep_comp_descriptor    ss_ep_comp;  
    struct list_head        urb_list;   //該端點的urb鏈表  
    void                *hcpriv;  
    struct ep_device        *ep_dev;    /* For sysfs info */    //端點設備  
  
    unsigned char *extra;   /* Extra descriptors */  
    int extralen;  
    int enabled;  
};  
[cpp] view plain copy
 
struct usb_interface_descriptor {  
    __u8  bLength;  
    __u8  bDescriptorType;  
  
    __u8  bInterfaceNumber;  
    __u8  bAlternateSetting;  
    __u8  bNumEndpoints;  
    __u8  bInterfaceClass;  
    __u8  bInterfaceSubClass;  
    __u8  bInterfaceProtocol;  
    __u8  iInterface;  
} __attribute__ ((packed));  
總結:

 

一個struct usb_device包含一個設備描述符(usb_device_descriptor)和配置結構數組(struct usb_host_config *)。

一個struct usb_host_config包含一個配置描述符(usb_config_descriptor)和接口結構數組(struct usb_interface)

一個usb_interface包含設置結構數組(struct  usb_host_interface *),因為一個接口可以有多個設置

一個usb_host_interface包含一個接口描述符和端點結構數組(struct usb_host_endpoint *)

一個usb_host_endpoint包含一個端點描述符。

 

[cpp] view plain copy
 
struct usb_driver {  
    const char *name;   //驅動程序的名字  
  
    int (*probe) (struct usb_interface *intf,  
              const struct usb_device_id *id);  
  
    void (*disconnect) (struct usb_interface *intf);  
  
    int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code,  
            void *buf);  
  
    int (*suspend) (struct usb_interface *intf, pm_message_t message);  
    int (*resume) (struct usb_interface *intf);  
    int (*reset_resume)(struct usb_interface *intf);  
  
    int (*pre_reset)(struct usb_interface *intf);  
    int (*post_reset)(struct usb_interface *intf);  
  
    const struct usb_device_id *id_table;   //驅動支持的設備列表  
  
    struct usb_dynids dynids;   //動態id  
    struct usbdrv_wrap drvwrap;  
    unsigned int no_dynamic_id:1;  
    unsigned int supports_autosuspend:1;  
    unsigned int soft_unbind:1;  
};  
struct usb_device_driver {  
    const char *name;  
  
    int (*probe) (struct usb_device *udev);  
    void (*disconnect) (struct usb_device *udev);  
  
    int (*suspend) (struct usb_device *udev, pm_message_t message);  
    int (*resume) (struct usb_device *udev, pm_message_t message);  
    struct usbdrv_wrap drvwrap;  
    unsigned int supports_autosuspend:1;  
};  
再次強調usb_driver是面向接口的,系統中有好多接口驅動,如hub_driver,usb_storage_driver。usb_device_driver是面向設備的,只有一個usb_generic_driver。

 

 

[cpp] view plain copy
 
struct usb_hcd {  
  
    /* 
     * housekeeping 
     */  
    struct usb_bus      self;       /* hcd is-a bus */  //hcd是一個usb總線  
    struct kref     kref;       /* reference counter */ //引用計數  
  
    const char      *product_desc;  /* product/vendor string */ //產品描述  
    int         speed;      /* Speed for this roothub. 
                         * May be different from 
                         * hcd->driver->flags & HCD_MASK 
                         */  
    char            irq_descr[24];  /* driver + bus # */  
  
    struct timer_list   rh_timer;   /* drives root-hub polling */   //root hub輪詢定時器  
    struct urb      *status_urb;    /* the current status urb */  
#ifdef CONFIG_USB_SUSPEND  
    struct work_struct  wakeup_work;    /* for remote wakeup */  
#endif  
  
    /* 
     * hardware info/state 
     */  
    const struct hc_driver  *driver;    /* hw-specific hooks */ //hc驅動  
  
    /* Flags that need to be manipulated atomically because they can 
     * change while the host controller is running.  Always use 
     * set_bit() or clear_bit() to change their values. 
     */  
    unsigned long       flags;  
#define HCD_FLAG_HW_ACCESSIBLE      0   /* at full power */  
#define HCD_FLAG_SAW_IRQ        1  
#define HCD_FLAG_POLL_RH        2   /* poll for rh status? */  
#define HCD_FLAG_POLL_PENDING       3   /* status has changed? */  
#define HCD_FLAG_WAKEUP_PENDING     4   /* root hub is resuming? */  
#define HCD_FLAG_RH_RUNNING     5   /* root hub is running? */  
#define HCD_FLAG_DEAD           6   /* controller has died? */  
  
    /* The flags can be tested using these macros; they are likely to 
     * be slightly faster than test_bit(). 
     */  
#define HCD_HW_ACCESSIBLE(hcd)  ((hcd)->flags & (1U << HCD_FLAG_HW_ACCESSIBLE))  
#define HCD_SAW_IRQ(hcd)    ((hcd)->flags & (1U << HCD_FLAG_SAW_IRQ))  
#define HCD_POLL_RH(hcd)    ((hcd)->flags & (1U << HCD_FLAG_POLL_RH))  
#define HCD_POLL_PENDING(hcd)   ((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING))  
#define HCD_WAKEUP_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))  
#define HCD_RH_RUNNING(hcd) ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING))  
#define HCD_DEAD(hcd)       ((hcd)->flags & (1U << HCD_FLAG_DEAD))  
  
    /* Flags that get set only during HCD registration or removal. */  
    unsigned        rh_registered:1;/* is root hub registered? */  
    unsigned        rh_pollable:1;  /* may we poll the root hub? */  
    unsigned        msix_enabled:1; /* driver has MSI-X enabled? */  
  
    /* The next flag is a stopgap, to be removed when all the HCDs 
     * support the new root-hub polling mechanism. */  
    unsigned        uses_new_polling:1;  
    unsigned        wireless:1; /* Wireless USB HCD */  
    unsigned        authorized_default:1;  
    unsigned        has_tt:1;   /* Integrated TT in root hub */  
  
    int         irq;        /* irq allocated */  
    void __iomem        *regs;      /* device memory/io */  
    u64         rsrc_start; /* memory/io resource start */  
    u64         rsrc_len;   /* memory/io resource length */  
    unsigned        power_budget;   /* in mA, 0 = no limit */  
  
    /* bandwidth_mutex should be taken before adding or removing 
     * any new bus bandwidth constraints: 
     *   1. Before adding a configuration for a new device. 
     *   2. Before removing the configuration to put the device into 
     *      the addressed state. 
     *   3. Before selecting a different configuration. 
     *   4. Before selecting an alternate interface setting. 
     * 
     * bandwidth_mutex should be dropped after a successful control message 
     * to the device, or resetting the bandwidth after a failed attempt. 
     */  
    struct mutex        *bandwidth_mutex;  
    struct usb_hcd      *shared_hcd;  
    struct usb_hcd      *primary_hcd;  
  
  
#define HCD_BUFFER_POOLS    4  
    struct dma_pool     *pool[HCD_BUFFER_POOLS];  
  
    int         state;  
#   define  __ACTIVE        0x01  
#   define  __SUSPEND       0x04  
#   define  __TRANSIENT     0x80  
  
#   define  HC_STATE_HALT       0  
#   define  HC_STATE_RUNNING    (__ACTIVE)  
#   define  HC_STATE_QUIESCING  (__SUSPEND|__TRANSIENT|__ACTIVE)  
#   define  HC_STATE_RESUMING   (__SUSPEND|__TRANSIENT)  
#   define  HC_STATE_SUSPENDED  (__SUSPEND)  
  
#define HC_IS_RUNNING(state) ((state) & __ACTIVE)  
#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)  
  
    /* more shared queuing code would be good; it should support 
     * smarter scheduling, handle transaction translators, etc; 
     * input size of periodic table to an interrupt scheduler. 
     * (ohci 32, uhci 1024, ehci 256/512/1024). 
     */  
  
    /* The HC driver's private data is stored at the end of 
     * this structure. 
     */  
    unsigned long hcd_priv[0]  
            __attribute__ ((aligned(sizeof(unsigned long))));  
};  
[cpp] view plain copy
 
struct hc_driver {  
    const char  *description;   /* "ehci-hcd" etc */  
    const char  *product_desc;  /* product/vendor string */  
    size_t      hcd_priv_size;  /* size of private data */  
  
    /* irq handler */  
    irqreturn_t (*irq) (struct usb_hcd *hcd);  
  
    int flags;  
#define HCD_MEMORY  0x0001      /* HC regs use memory (else I/O) */  
#define HCD_LOCAL_MEM   0x0002      /* HC needs local memory */  
#define HCD_SHARED  0x0004      /* Two (or more) usb_hcds share HW */  
#define HCD_USB11   0x0010      /* USB 1.1 */  
#define HCD_USB2    0x0020      /* USB 2.0 */  
#define HCD_USB3    0x0040      /* USB 3.0 */  
#define HCD_MASK    0x0070  
  
    /* called to init HCD and root hub */  
    int (*reset) (struct usb_hcd *hcd);  
    int (*start) (struct usb_hcd *hcd);  
  
    /* NOTE:  these suspend/resume calls relate to the HC as 
     * a whole, not just the root hub; they're for PCI bus glue. 
     */  
    /* called after suspending the hub, before entering D3 etc */  
    int (*pci_suspend)(struct usb_hcd *hcd, bool do_wakeup);  
  
    /* called after entering D0 (etc), before resuming the hub */  
    int (*pci_resume)(struct usb_hcd *hcd, bool hibernated);  
  
    /* cleanly make HCD stop writing memory and doing I/O */  
    void    (*stop) (struct usb_hcd *hcd);  
  
    /* shutdown HCD */  
    void    (*shutdown) (struct usb_hcd *hcd);  
  
    /* return current frame number */  
    int (*get_frame_number) (struct usb_hcd *hcd);  
  
    /* manage i/o requests, device state */  
    int (*urb_enqueue)(struct usb_hcd *hcd,  
                struct urb *urb, gfp_t mem_flags);  
    int (*urb_dequeue)(struct usb_hcd *hcd,  
                struct urb *urb, int status);  
  
    /* 
     * (optional) these hooks allow an HCD to override the default DMA 
     * mapping and unmapping routines.  In general, they shouldn't be 
     * necessary unless the host controller has special DMA requirements, 
     * such as alignment contraints.  If these are not specified, the 
     * general usb_hcd_(un)?map_urb_for_dma functions will be used instead 
     * (and it may be a good idea to call these functions in your HCD 
     * implementation) 
     */  
    int (*map_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb,  
                   gfp_t mem_flags);  
    void    (*unmap_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb);  
  
    /* hw synch, freeing endpoint resources that urb_dequeue can't */  
    void    (*endpoint_disable)(struct usb_hcd *hcd,  
            struct usb_host_endpoint *ep);  
  
    /* (optional) reset any endpoint state such as sequence number 
       and current window */  
    void    (*endpoint_reset)(struct usb_hcd *hcd,  
            struct usb_host_endpoint *ep);  
  
    /* root hub support */  
    int (*hub_status_data) (struct usb_hcd *hcd, char *buf);  
    int (*hub_control) (struct usb_hcd *hcd,  
                u16 typeReq, u16 wValue, u16 wIndex,  
                char *buf, u16 wLength);  
    int (*bus_suspend)(struct usb_hcd *);  
    int (*bus_resume)(struct usb_hcd *);  
    int (*start_port_reset)(struct usb_hcd *, unsigned port_num);  
  
        /* force handover of high-speed port to full-speed companion */  
    void    (*relinquish_port)(struct usb_hcd *, int);  
        /* has a port been handed over to a companion? */  
    int (*port_handed_over)(struct usb_hcd *, int);  
  
        /* CLEAR_TT_BUFFER completion callback */  
    void    (*clear_tt_buffer_complete)(struct usb_hcd *,  
                struct usb_host_endpoint *);  
  
    /* xHCI specific functions */  
        /* Called by usb_alloc_dev to alloc HC device structures */  
    int (*alloc_dev)(struct usb_hcd *, struct usb_device *);  
        /* Called by usb_disconnect to free HC device structures */  
    void    (*free_dev)(struct usb_hcd *, struct usb_device *);  
    /* Change a group of bulk endpoints to support multiple stream IDs */  
    int (*alloc_streams)(struct usb_hcd *hcd, struct usb_device *udev,  
        struct usb_host_endpoint **eps, unsigned int num_eps,  
        unsigned int num_streams, gfp_t mem_flags);  
    /* Reverts a group of bulk endpoints back to not using stream IDs. 
     * Can fail if we run out of memory. 
     */  
    int (*free_streams)(struct usb_hcd *hcd, struct usb_device *udev,  
        struct usb_host_endpoint **eps, unsigned int num_eps,  
        gfp_t mem_flags);  
  
    /* Bandwidth computation functions */  
    /* Note that add_endpoint() can only be called once per endpoint before 
     * check_bandwidth() or reset_bandwidth() must be called. 
     * drop_endpoint() can only be called once per endpoint also. 
     * A call to xhci_drop_endpoint() followed by a call to 
     * xhci_add_endpoint() will add the endpoint to the schedule with 
     * possibly new parameters denoted by a different endpoint descriptor 
     * in usb_host_endpoint.  A call to xhci_add_endpoint() followed by a 
     * call to xhci_drop_endpoint() is not allowed. 
     */  
        /* Allocate endpoint resources and add them to a new schedule */  
    int (*add_endpoint)(struct usb_hcd *, struct usb_device *,  
                struct usb_host_endpoint *);  
        /* Drop an endpoint from a new schedule */  
    int (*drop_endpoint)(struct usb_hcd *, struct usb_device *,  
                 struct usb_host_endpoint *);  
        /* Check that a new hardware configuration, set using 
         * endpoint_enable and endpoint_disable, does not exceed bus 
         * bandwidth.  This must be called before any set configuration 
         * or set interface requests are sent to the device. 
         */  
    int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);  
        /* Reset the device schedule to the last known good schedule, 
         * which was set from a previous successful call to 
         * check_bandwidth().  This reverts any add_endpoint() and 
         * drop_endpoint() calls since that last successful call. 
         * Used for when a check_bandwidth() call fails due to resource 
         * or bandwidth constraints. 
         */  
    void    (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);  
        /* Returns the hardware-chosen device address */  
    int (*address_device)(struct usb_hcd *, struct usb_device *udev);  
        /* Notifies the HCD after a hub descriptor is fetched. 
         * Will block. 
         */  
    int (*update_hub_device)(struct usb_hcd *, struct usb_device *hdev,  
            struct usb_tt *tt, gfp_t mem_flags);  
    int (*reset_device)(struct usb_hcd *, struct usb_device *);  
        /* Notifies the HCD after a device is connected and its 
         * address is set 
         */  
    int (*update_device)(struct usb_hcd *, struct usb_device *);  
};  
[cpp] view plain copy
 
struct usb_bus {  
    struct device *controller;  /* host/master side hardware */ //主機控制器端的device結構  
    int busnum;         /* Bus number (in order of reg) */  //總線編號  
    const char *bus_name;       /* stable id (PCI slot_name etc) */ //總線名字  
    u8 uses_dma;            /* Does the host controller use DMA? */  
    u8 uses_pio_for_control;    /* 
                     * Does the host controller use PIO 
                     * for control transfers? 
                     */  
    u8 otg_port;            /* 0, or number of OTG/HNP port */  
    unsigned is_b_host:1;       /* true during some HNP roleswitches */  
    unsigned b_hnp_enable:1;    /* OTG: did A-Host enable HNP? */  
    unsigned sg_tablesize;      /* 0 or largest number of sg list entries */  
  
    int devnum_next;        /* Next open device number in 
                     * round-robin allocation */  
  
    struct usb_devmap devmap;   /* device address allocation map */  
    struct usb_device *root_hub;    /* Root hub */  //指向根hub  
    struct usb_bus *hs_companion;   /* Companion EHCI bus, if any */  
    struct list_head bus_list;  /* list of busses */    //鏈接到所有的ub總線的連接件  
  
    int bandwidth_allocated;    /* on this bus: how much of the time 
                     * reserved for periodic (intr/iso) 
                     * requests is used, on average? 
                     * Units: microseconds/frame. 
                     * Limits: Full/low speed reserve 90%, 
                     * while high speed reserves 80%. 
                     */  
    int bandwidth_int_reqs;     /* number of Interrupt requests */  //中斷傳輸的數量  
    int bandwidth_isoc_reqs;    /* number of Isoc. requests */  //等時傳輸的數量  
  
#ifdef CONFIG_USB_DEVICEFS  
    struct dentry *usbfs_dentry;    /* usbfs dentry entry for the bus */  
#endif  
  
#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)  
    struct mon_bus *mon_bus;    /* non-null when associated */  
    int monitored;          /* non-zero when monitored */  
#endif  
};  
2. usb框架的初始化

 

[cpp] view plain copy
 
static int __init usb_init(void)  
{  
    int retval;  
    if (nousb) {  
        pr_info("%s: USB support disabled\n", usbcore_name);  
        return 0;  
    }  
  
    retval = usb_debugfs_init();    //usb debugfs初始化  
    if (retval)  
        goto out;  
  
    retval = bus_register(&usb_bus_type);   //注冊usb 總線  
    if (retval)  
        goto bus_register_failed;  
    retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb); //注冊usb總線的通知塊  
    if (retval)  
        goto bus_notifier_failed;  
    retval = usb_major_init();  //注冊主設備號為180的usb字符設備  
    if (retval)  
        goto major_init_failed;  
    retval = usb_register(&usbfs_driver);   //注冊一個usb_driver usbfs_driver  
    if (retval)  
        goto driver_register_failed;  
    retval = usb_devio_init();  //注冊主設備號為189,次設備數為64*128  
    if (retval)  
        goto usb_devio_init_failed;  
    retval = usbfs_init();  //注冊usb_fs_type文件系統  
    if (retval)  
        goto fs_init_failed;  
    retval = usb_hub_init();    //注冊hub_driver,創建khub內核線程  
    if (retval)  
        goto hub_init_failed;  
    retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);  //注冊usb系統唯一的usb_device_driver usb_generic_driver  
    if (!retval)  
        goto out;  
  
    usb_hub_cleanup();  
hub_init_failed:  
    usbfs_cleanup();  
fs_init_failed:  
    usb_devio_cleanup();  
usb_devio_init_failed:  
    usb_deregister(&usbfs_driver);  
driver_register_failed:  
    usb_major_cleanup();  
major_init_failed:  
    bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);  
bus_notifier_failed:  
    bus_unregister(&usb_bus_type);  
bus_register_failed:  
    usb_debugfs_cleanup();  
out:  
    return retval;  
}  
[cpp] view plain copy
 
static int usb_debugfs_init(void)  
{  
    usb_debug_root = debugfs_create_dir("usb", NULL);  
    if (!usb_debug_root)  
        return -ENOENT;  
  
    usb_debug_devices = debugfs_create_file("devices", 0444,  
                        usb_debug_root, NULL,  
                        &usbfs_devices_fops);  
    if (!usb_debug_devices) {  
        debugfs_remove(usb_debug_root);  
        usb_debug_root = NULL;  
        return -ENOENT;  
    }  
  
    return 0;  
}  
[cpp] view plain copy
 
int usb_major_init(void)  
{  
    int error;  
  
    error = register_chrdev(USB_MAJOR, "usb", &usb_fops);  
    if (error)  
        printk(KERN_ERR "Unable to get major %d for usb devices\n",  
               USB_MAJOR);  
  
    return error;  
}  
[cpp] view plain copy
 
int __init usb_devio_init(void)  
{  
    int retval;  
  
    retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,  
                    "usb_device");  
    if (retval) {  
        printk(KERN_ERR "Unable to register minors for usb_device\n");  
        goto out;  
    }  
    cdev_init(&usb_device_cdev, &usbdev_file_operations);  
    retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX);  
    if (retval) {  
        printk(KERN_ERR "Unable to get usb_device major %d\n",  
               USB_DEVICE_MAJOR);  
        goto error_cdev;  
    }  
#ifdef CONFIG_USB_DEVICE_CLASS  
    usb_classdev_class = class_create(THIS_MODULE, "usb_device");  
    if (IS_ERR(usb_classdev_class)) {  
        printk(KERN_ERR "Unable to register usb_device class\n");  
        retval = PTR_ERR(usb_classdev_class);  
        cdev_del(&usb_device_cdev);  
        usb_classdev_class = NULL;  
        goto out;  
    }  
    /* devices of this class shadow the major:minor of their parent 
     * device, so clear ->dev_kobj to prevent adding duplicate entries 
     * to /sys/dev 
     */  
    usb_classdev_class->dev_kobj = NULL;  
#endif  
    usb_register_notify(&usbdev_nb);  
out:  
    return retval;  
  
error_cdev:  
    unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX);  
    goto out;  
}  
[cpp] view plain copy
 
int usb_hub_init(void)  
{  
    if (usb_register(&hub_driver) < 0) {  
        printk(KERN_ERR "%s: can't register hub driver\n",  
            usbcore_name);  
        return -1;  
    }  
  
    khubd_task = kthread_run(hub_thread, NULL, "khubd");  
    if (!IS_ERR(khubd_task))  
        return 0;  
  
    /* Fall through if kernel_thread failed */  
    usb_deregister(&hub_driver);  
    printk(KERN_ERR "%s: can't start khubd\n", usbcore_name);  
  
    return -1;  
}  
[cpp] view plain copy
 
int usb_register_device_driver(struct usb_device_driver *new_udriver,  
        struct module *owner)  
{  
    int retval = 0;  
  
    if (usb_disabled())  
        return -ENODEV;  
  
    new_udriver->drvwrap.for_devices = 1;  
    new_udriver->drvwrap.driver.name = (char *) new_udriver->name;  
    new_udriver->drvwrap.driver.bus = &usb_bus_type;  
    new_udriver->drvwrap.driver.probe = usb_probe_device;  
    new_udriver->drvwrap.driver.remove = usb_unbind_device;  
    new_udriver->drvwrap.driver.owner = owner;  
  
    retval = driver_register(&new_udriver->drvwrap.driver);  
  
    if (!retval) {  
        pr_info("%s: registered new device driver %s\n",  
            usbcore_name, new_udriver->name);  
        usbfs_update_special();  
    } else {  
        printk(KERN_ERR "%s: error %d registering device "  
            "   driver %s\n",  
            usbcore_name, retval, new_udriver->name);  
    }  
  
    return retval;  
}  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM