前面我們學習了USB 驅動的一個描述符,下面來學習 USB 驅動的幾個重要數據結構
位於include\linux\usb.h
一、struct usb_device 設備函數
struct usb_device {
int devnum; //devnum只是usb設備在一條usb總線上的編號.一條usb_bus_type類型的總線上最多可以連上128個設備
char devpath [16]; /* Use in messages: /port/port/...*/ //對於root hub.會將dev->devpath[0]=’0’
enum usb_device_state state; //設備的狀態Attached,Powered,Default,Address,Configured,Suspended;
//Attached表示設備已經連接到usb接口上了,是hub檢測到設備時的初始狀態。那么這里所謂的USB_STATE_NOTATTACHED就是表示設備並沒有Attached。
//Address狀態表示主機分配了一個唯一的地址給設備,此時設備可以使用缺省管道響應主機的請求
//Configured狀態表示設備已經被主機配置過了,也就是協議里說的處理了一個帶有非0值的SetConfiguration()請求,此時主機可以使用設備提供的所有功能
//Suspended掛起狀態,為了省電,設備在指定的時間內,3ms吧,如果沒有發生總線傳輸,就要進入掛起狀態。此時,usb設備要自己維護包括地址、配置在內的信息
enum usb_device_speed speed; /* high/full/low (or error) */
struct usb_tt *tt; //如果一個高速設備里有這么一個TT,那么就可以連接低速/全速設備,如不然,那低速/全速設備沒法用,只能連接到OHCI/UHCI那邊出來的hub口里。
int ttport; //如果一個高速設備里有這么一個TT,那么就可以連接低速/全速設備,如不然,那低速/全速設備沒法用,只能連接到OHCI/UHCI那邊出來的hub口里。
unsigned int toggle[2]; /* one bit for each endpoint //他實際上就是一個位圖.IN方向的是toggle[0].OUT方向的是toggle[1].其實,這個數組中的每一位表示ep的toggle值
* ([0] = IN, [1] = OUT) */它里面的每一位表示的就是每個端點當前發送或接收的數據包是DATA0還是DATA1
struct usb_device *parent; /* our hub, unless we're the root */
//USB設備是從Root Hub開始,一個一個往外面連的,比如Root Hub有4個口,每個口連一個USB設備,比如其中有一個是Hub,那么這個Hub有可以繼續有多個口,於是一級一級的往下連,
//最終連成了一棵樹。
struct usb_bus *bus; /* Bus we're part of */設備所在的總線
struct usb_host_endpoint ep0; //端點0的特殊地位決定了她必將受到特殊的待遇,在struct usb_device對象產生的時候它就要初始化
struct device dev; /* Generic device interface */嵌入到struct usb_device結構里的struct device結構
struct usb_device_descriptor descriptor;/* Descriptor */設備描述符,此結構體的bMaxPacketSize0 filed保存了端點0的maximum packet size
struct usb_host_config *config; //設備擁有的所有配置
struct usb_host_config *actconfig;//設備正在使用的配置
struct usb_host_endpoint *ep_in[16];//ep_in[16],359行,ep_out[16],除了端點0,一個設備即使在高速模式下也最多只能再有15個IN端點和15個OUT端點,端點0太特殊了,
struct usb_host_endpoint *ep_out[16];//對應的管道是Message管道,又能進又能出特能屈能伸的那種,所以這里的ep_in和ep_out數組都有16個值
char **rawdescriptors; /* Raw descriptors for each config */
unsigned short bus_mA; /* Current available from the bus */這個值是在host controller的驅動程序中設置的,通常來講,計算機的usb端口可以提供500mA的電流
u8 portnum; //不管是root hub還是一般的hub,你的USB設備總歸要插在一個hub的端口上才能用,portnum就是那個端口號。
u8 level; //層次,也可以說是級別,表征usb設備樹的級連關系。Root Hub的level當然就是0,其下面一層就是level 1,再下面一層就是level 2,依此類推
unsigned discon_suspended:1; /* Disconnected while suspended */
unsigned have_langid:1; /* whether string_langid is valid */
int string_langid; /* language ID for strings */
/* static strings from the device */
char *product; /* iProduct string, if present */
char *manufacturer; /* iManufacturer string, if present */
char *serial; /* iSerialNumber string, if present */
//分別用來保存產品、廠商和序列號對應的字符串描述符信息
struct list_head filelist;
#ifdef CONFIG_USB_DEVICE_CLASS
struct device *usb_classdev;
#endif
#ifdef CONFIG_USB_DEVICEFS
struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */
#endif
/*
* Child devices - these can be either new devices
* (if this is a hub device), or different instances
* of this same device.
*
* Each instance needs its own set of data structures.
*/
int maxchild; /* Number of ports if hub */
struct usb_device *children[USB_MAXCHILDREN];
int pm_usage_cnt; /* usage counter for autosuspend */
u32 quirks; //quirk就是用來判斷這些有毛病的產品啥毛病的
#ifdef CONFIG_PM
struct delayed_work autosuspend; /* for delayed autosuspends */
struct mutex pm_mutex; /* protects PM operations */
unsigned long last_busy; /* time of last use */
int autosuspend_delay; /* in jiffies */
unsigned auto_pm:1; /* autosuspend/resume in progress */
unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */
unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
unsigned autoresume_disabled:1; /* disabled by the user */
#endif
};
二、struct usb_host_config 配置函數
struct usb_host_config {
struct usb_config_descriptor desc;
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]; //usb接口的緩存
unsigned char *extra; /* Extra descriptors */
int extralen;
};
三、struct usb_interface 接口函數
usb_interface字面意思既是接口,什么的接口:設備的接口。
為什么會出現這樣的類型出來,根據實際情況,例如:
一個設備有兩種功能 一個鍵盤 一個音頻,兩種接口,那這樣肯定得要兩個驅動程序,一個是鍵盤驅動程序,一個是音頻流驅動程序。兩種功能整合在一起稱為一個設備。但是不同的接口需要不同的驅動,音頻驅動 和鍵盤驅動。用interface來區分,就有了接口類型
struct usb_interface {
/* array of alternate settings for this interface,
* stored in no particular order */
struct usb_host_interface *altsetting; // 當前接口的可選設置
/* the currently active alternate setting */
struct usb_host_interface *cur_altsetting; // 當前接口使用的設置
/* number of alternate settings */
unsigned num_altsetting; // 當前接口具有的可選設置總數
/* If there is an interface association descriptor then it will list
* the associated interfaces */
struct usb_interface_assoc_descriptor *intf_assoc;
/* minor number this interface is * bound to */
int minor; // 當前接口的在主設備號為USB_MAJOR時的子設備號,minor只在USB_MAJOR起作用時起
作用。 usb設備沒有與其它任何子系統關聯,就需要在對應驅動的probe函數里使用usb_register_dev函數來注冊並獲得主設備號USB_MAJOR。如果usb設備關聯了其它子系統,則需要在對應驅動的probe函數里使用相應的注冊函數,USB_MAJOR也就該干嗎干嗎去,用不着它了。比如,usb鍵盤關聯了input子系統,驅動對應drivers/hid/usbhid目錄下的usbkbd.c文件,在它的probe函數里可以看到使用了input_register_device來注冊一個輸入設備。
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 resetting_device:1; /* true: bandwidth alloc after reset */
struct device dev; /* interface specific device info */ // linux設備模型里的device嵌在這兒的對象
struct device *usb_dev; // 當接口使用USB_MAJOR作為主設備號時,usb_dev才會用到, usb_register_dev和usb_deregister_dev使用這個結構體,usb_dev指向的
就是usb_register_dev函數里創建的usb class device。
atomic_t pm_usage_cnt; /* usage counter for autosuspend */
struct work_struct reset_ws; /* for resets in atomic context */
}
struct usb_interface中的struct usb_host_interface *cur_altsetting成員,表示當前正在使用的設置
1、struct usb_host_interface
struct usb_host_interface
{
struct usb_interface_descriptor desc;//usb描述符,主要有四種usb描述符,設備描述符,配置描述符,接口描述符和端點描述符,協議里規定一個usb設備是必須支持這四大描述符的。
//usb描述符放在usb設備的eeprom里邊
/* 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_interface結構里,而是放在表示接口設置的struct usb_host_interface結構里。
四、struct usb_host_endpoint 端點函數
struct usb_host_endpoint
{
struct usb_endpoint_descriptor desc; //端點描述符
struct list_head urb_list;//端點要處理的urb隊列.urb是usb通信的主角,設備中的每個端點都可以處理一個urb隊列.要想和你的usb通信,就得創建一個urb,並且為它賦好值,
//交給咱們的usb core,它會找到合適的host controller,從而進行具體的數據傳輸
void *hcpriv;//這是提供給HCD(host controller driver)用的
struct ep_device *ep_dev; /* For sysfs info */
unsigned char *extra; /* Extra descriptors */
int extralen;
};
參考:
