轉 內核usb驅動分析

本文主要分析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;
};
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));
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;  

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

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

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

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

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

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

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

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

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

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

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

}

原文地址:
https://blog.csdn.net/duan_xiaosu/article/details/68487314

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章