usb描述符簡述(二)
title: usb描述符簡述
tags: linux
date: 2018/12/18/ 18:25:23
toc: true
---
usb描述符簡述
轉載自cnblog
具體描述符 https://blog.csdn.net/hushiganghu/article/details/54929066
在USB描述符中,從上到下分為四個層次:
- USB裝置描述符(usb_device_descriptor)
- USB配置描述符(usb_config_descriptor)、
- USB介面描述符(usb_interface_descriptor)、
- USB端點描述符(usb_endpoint_descriptor)、
- USB介面描述符(usb_interface_descriptor)、
- USB配置描述符(usb_config_descriptor)、
一個設定描述符可以有多個配置描述符
一個配置描述符可以有多個介面描述符(比如音效卡驅動,就有兩個介面:錄音介面和播放介面)
一個介面描述符可以有多個端點描述符,一個USB介面代表一個邏輯上的裝置,比如音效卡驅動,就有兩個介面:錄音介面和播放介面
一個端點只有一個方向,端點0可讀可寫
比如集成了鍵盤和滑鼠的USB裝置,裡面就是兩個interface,一個是鍵盤,另一個是滑鼠。Interface之間通常是隔離的,互相不干擾。
每個Interface(介面)下面有一個或者多個Endpoint(端點),這也是邏輯概念,比如QQ要通訊,可能開好幾個埠,同樣U盤要跟主機通訊,要有控制訊號和資料訊號,這些都是不同的端點。端點是USB裝置通訊的基本單位,所有通訊幾乎都是從端點發起的。
裝置描述符
struct usb_device_descriptor { __u8 bLength; //本描述符的size __u8 bDescriptorType; //描述符的型別,這裡是裝置描述符DEVICE __u16 bcdUSB; //指明usb的版本,比如usb2.0 __u8 bDeviceClass; //類 __u8 bDeviceSubClass; //子類 __u8 bDeviceProtocol; //指定協議 __u8 bMaxPacketSize0; //端點0對應的最大包大小 __u16 idVendor; //廠家ID __u16 idProduct; //產品ID __u16 bcdDevice; //裝置的釋出號 __u8 iManufacturer; //字串描述符中廠家ID的索引 __u8 iProduct; //字串描述符中產品ID的索引 __u8 iSerialNumber; //字串描述符中裝置序列號的索引 __u8 bNumConfigurations; //配置描述符的個數,表示有多少個配置描述符 } __attribute__ ((packed));
USB裝置描述符位於USB裝置結構體usb_device中的成員descriptor中
同樣地,配置、介面、端點描述符也是位於USB配置、介面、端點結構體中,不過這3個對於我們寫驅動的不是很常用
usb_device結構體如下所示:
struct usb_device {
int devnum; //裝置號,是在USB匯流排的地址
char devpath [16]; //用於訊息的裝置ID字串
enum usb_device_state state; //裝置狀態:已配置、未連線等等
enum usb_device_speed speed; //裝置速度:高速、全速、低速或錯誤
struct usb_tt *tt; //處理傳輸者資訊;用於低速、全速裝置和高速HUB
int ttport; //位於tt HUB的裝置口
unsigned int toggle[2]; //每個端點的佔一位,表明端點的方向([0] = IN, [1] = OUT)
struct usb_device *parent; //上一級HUB指標
struct usb_bus *bus; //匯流排指標
struct usb_host_endpoint ep0; //端點0資料
struct device dev; //一般的裝置介面資料結構
struct usb_device_descriptor descriptor; //USB裝置描述符,
struct usb_host_config *config; //裝置的所有配置結構體,配置結構體裡包含了配置描述符
struct usb_host_config *actconfig; //被啟用的裝置配置
struct usb_host_endpoint *ep_in[16]; //輸入端點陣列
struct usb_host_endpoint *ep_out[16]; //輸出端點陣列
char **rawdescriptors; //每個配置的raw描述符
unsigned short bus_mA; //可使用的匯流排電流
u8 portnum; //父埠號
u8 level; //USB HUB的層數
unsigned can_submit:1; //URB可被提交標誌
unsigned discon_suspended:1; //暫停時斷開標誌
unsigned persist_enabled:1; //USB_PERSIST使能標誌
unsigned have_langid:1; //string_langid存在標誌
unsigned authorized:1;
unsigned authenticated:1;
unsigned wusb:1; //無線USB標誌
int string_langid; //字串語言ID
/* static strings from the device */ //裝置的靜態字串
char *product; //產品名
char *manufacturer; //廠商名
char *serial; //產品串號
struct list_head filelist; //此裝置開啟的usbfs檔案
#ifdef CONFIG_USB_DEVICE_CLASS
struct device *usb_classdev; //使用者空間訪問的為usbfs裝置建立的USB類裝置
#endif
#ifdef CONFIG_USB_DEVICEFS
struct dentry *usbfs_dentry; //裝置的usbfs入口
#endif
int maxchild; //(若為HUB)介面數
struct usb_device *children[USB_MAXCHILDREN];//連線在這個HUB上的子裝置
int pm_usage_cnt; //自動掛起的使用計數
u32 quirks;
atomic_t urbnum; //這個裝置所提交的URB計數
unsigned long active_duration; //啟用後使用計時
#ifdef CONFIG_PM //電源管理相關
struct delayed_work autosuspend; //自動掛起的延時
struct work_struct autoresume; //(中斷的)自動喚醒需求
struct mutex pm_mutex; //PM的互斥鎖
unsigned long last_busy; //最後使用的時間
int autosuspend_delay;
unsigned long connect_time; //第一次連線的時間
unsigned auto_pm:1; //自動掛起/喚醒
unsigned do_remote_wakeup:1; //遠端喚醒
unsigned reset_resume:1; //使用復位替代喚醒
unsigned autosuspend_disabled:1; //掛起關閉
unsigned autoresume_disabled:1; //喚醒關閉
unsigned skip_sys_resume:1; //跳過下個系統喚醒
#endif
struct wusb_dev *wusb_dev; //(如果為無線USB)連線到WUSB特定的資料結構
};
配置描述符
struct usb_config_descriptor {
__u8 bLength; //描述符的長度
__u8 bDescriptorType; //描述符型別的編號
__le16 wTotalLength; //配置 所返回的所有資料的大小
__u8 bNumInterfaces; //配置 所支援的介面個數, 表示有多少個介面描述符
__u8 bConfigurationValue; //Set_Configuration命令需要的引數值
__u8 iConfiguration; //描述該配置的字串的索引值
__u8 bmAttributes; //供電模式的選擇
__u8 bMaxPower; //裝置從匯流排提取的最大電流
} __attribute__ ((packed));
介面描述符
USB介面只處理一種USB邏輯連線。一個USB介面代表一個邏輯上的裝置,比如音效卡驅動,就有兩個介面:錄音介面和播放介面
這可以在windows系統中看出,有時插入一個USB裝置後,系統會識別出多個裝置,並安裝相應多個的驅動。
struct usb_interface_descriptor {
__u8 bLength; //描述符的長度
__u8 bDescriptorType; //描述符型別的編號
__u8 bInterfaceNumber; //介面的編號
__u8 bAlternateSetting; //備用的介面描述符編號,提供不同質量的服務引數.
__u8 bNumEndpoints; //要使用的端點個數(不包括端點0), 表示有多少個端點描述符,比如滑鼠就只有一個端點
__u8 bInterfaceClass; //介面型別,與驅動的id_table
__u8 bInterfaceSubClass; //介面子型別
__u8 bInterfaceProtocol; //介面所遵循的協議
__u8 iInterface; //描述該介面的字串索引值
} __attribute__ ((packed)
它位於usb_interface->cur_altsetting->desc 這個成員結構體裡,
usb_interface結構體如下所示:
struct usb_interface {
struct usb_host_interface *altsetting; /* 包含所有可用於該介面的可選設定的介面結構陣列。每個 struct usb_host_interface 包含一套端點配置(即struct usb_host_endpoint結構所定義的端點配置。這些介面結構沒有特別的順序。*/
struct usb_host_interface *cur_altsetting; /* 指向altsetting內部的指標,表示當前啟用的介面配置*/
unsigned num_altsetting; /* 可選設定的數量*/
/* If there is an interface association descriptor then it will list the associated interfaces */
struct usb_interface_assoc_descriptor *intf_assoc;
int minor; /* 如果繫結到這個介面的 USB 驅動使用 USB 主裝置號, 這個變數包含由 USB 核心分配給介面的次裝置號. 這隻在一個成功的呼叫 usb_register_dev後才有效。*/
... ...
}
cur_altsetting成員的結構體是usb_host_interface,如下:
struct usb_host_interface {
struct usb_interface_descriptor desc; //當前被啟用的介面描述符
struct usb_host_endpoint *endpoint; /* 這個介面的所有端點結構體的聯合陣列*/
char *string; /* 介面描述字串 */
unsigned char *extra; /* 額外的描述符 */
int extralen;
};
端點描述符
struct usb_endpoint_descriptor {
__u8 bLength; //描述符的長度
__u8 bDescriptorType; //描述符型別的編號
__u8 bEndpointAddress; //端點編號,比如端點1,就是1
__u8 bmAttributes; //端點的屬性, 比如中斷傳輸型別,輸入型別
__le16 wMaxPacketSize; //一個端點的最大包大小,
__u8 bInterval; //間隔時間,用在中斷傳輸上,比如間隔時間查詢滑鼠的資料
/* NOTE: these two are _only_ in audio endpoints. */
/* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
__u8 bRefresh;
__u8 bSynchAddress;
} __attribute__ ((packed));
比如端點0,就位於usb_interface->cur_altsetting->desc->endpoint[0].desc
其中endpoint的結構體為usb_host_endpoint,如下所示:
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;//使能的話urb才能被提交到此埠
};