您的位置:首页 > 其它

USB驱动框架分析1

2017-03-30 14:57 501 查看
本文主要分析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

print?

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;  
};  



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

print?

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));  



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

print?

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;  
};  



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

print?

struct usb_config_descriptor {  
    __u8  bLength;  
    __u8  bDescriptorType;  
  
    __le16 wTotalLength;  
    __u8  bNumInterfaces;  
    __u8  bConfigurationValue;  
    __u8  iConfiguration;  
    __u8  bmAttributes;  
    __u8  bMaxPower;  
} __attribute__ ((packed));  



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

print?

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 */  
};  



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

print?

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;  
};  



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

print?

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_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

print?

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;  
};  



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

print?

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_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

print?

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;  
};  



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

print?

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))));  
};  



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

print?

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 *);  
};  



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

print?

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  
};  



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

print?

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;  
}  



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

print?

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;  
}  



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

print?

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;  
}  



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

print?

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;  
}  



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

print?

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;  
}  



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

print?

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;  
}  



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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  USB驱动框架分析