USB學(xué)習(xí)筆記一之描述符

  1. 邏輯層次及描述符

邏輯上,usb包含設(shè)備(Device),配置(Configuration),接口(Interface)和端點(diǎn)(Endpoint)四個層次。設(shè)備通常有一個或多個配置,配置通常有一個或多個接口,接口有零個或多個端點(diǎn)(端點(diǎn)0應(yīng)該是沒有算進(jìn)去)。有多個配置的設(shè)備,任意時刻只能有一個配置處于激活狀態(tài)。在這四個層次之外,還有一個設(shè)置(setting),它與接口相關(guān),一個接口可以有多個設(shè)置(setting)。有多個設(shè)置(setting)的接口,任意時刻也只能有一個設(shè)置(setting)生效。

這四個層次都有相應(yīng)的描述符(另外一個常用的描述符是字符串描述符),它們都可以通過GET_DESCRIPTOR命令獲取。GET_DESCRIPTOR命令需要指定描述符類型,描述符索引等參數(shù)。需要注意的是,只能指定設(shè)備,配置和字符串三種描述符類型,而不能指定接口和端點(diǎn)這兩種描述符類型。這是因為在獲取配置描述符時,會把它包含的所有接口和端點(diǎn)描述符一次性獲取過來。因此,獲取配置描述符時,得到的內(nèi)容將是:配置描述符,接口0的描述符,接口0的端點(diǎn)描述符,接口1的描述符,接口1的端點(diǎn)描述符,直至接口n。另外,GET_DESCRIPTOR命令的描述符索引參數(shù),只對配置描述符和字符串描述符有效,分別用于獲取指定的配置描述符和字符串描述符,而對設(shè)備描述符無效(原因應(yīng)該是一個設(shè)備只有一個設(shè)備描述符)。

獲取設(shè)備描述符后,可以知道此設(shè)備支持幾個配置。獲取配置描述符后,可以得到此配置的編號(bConfigurationValue,應(yīng)該不是從0開始編號),還可以知道此配置支持幾個接口。解析接口描述符后,可以得到此接口的編號(bInterfaceNumber,從0開始編號,直至接口數(shù)目減1),還可以知道此接口支持幾個端點(diǎn)。注意,接口描述符里,并沒有說明此接口支持幾個設(shè)置(setting)。獲取配置描述符時,會一并獲取它支持的接口描述符,如果獲取到相同編號(bInterfaceNumber)的多個接口描述符,則是同一個接口的不同設(shè)置(setting),這些接口描述符的設(shè)置(setting)編號(bAlternateSetting,從0開始編號,直至設(shè)置(setting)數(shù)目減1)應(yīng)該不同。

  1. 描述符詳情

2.1 設(shè)備描述符

struct usb_device_descriptor {
    __u8  bLength;            // 18
    __u8  bDescriptorType;    // USB_DT_DEVICE,0x01
    __le16 bcdUSB;            // usb spec版本號,對應(yīng) sysfs 中的 version
    __u8  bDeviceClass;       // 見第3節(jié),“類別(Class)和協(xié)議(Protocol)”
    __u8  bDeviceSubClass;
    __u8  bDeviceProtocol;
    __u8  bMaxPacketSize0;    // 端點(diǎn)0一次可以處理的最大字節(jié)數(shù)
    __le16 idVendor;          // 廠商id
    __le16 idProduct;         // 產(chǎn)品id
    __le16 bcdDevice;         // 設(shè)備版本號
    __u8  iManufacturer;      // 廠商對應(yīng)的字符串描述符的索引值
    __u8  iProduct;           // 產(chǎn)品對應(yīng)的字符串描述符的索引值
    __u8  iSerialNumber;      // 序列號對應(yīng)的字符串描述符的索引值
    __u8  bNumConfigurations; // 當(dāng)前速度模式下的配置數(shù)目(不是設(shè)備支持的所有配置數(shù)目)。
} __attribute__ ((packed));

2.2 配置描述符

struct usb_config_descriptor {
    __u8  bLength;             // 9
    __u8  bDescriptorType;     // USB_DT_CONFIG, 0x02

    __le16 wTotalLength;       // GET_DESCRIPTOR 標(biāo)準(zhǔn)請求返回的總長度
    __u8  bNumInterfaces;      // 此配置包含的接口數(shù)目
    __u8  bConfigurationValue; // 可以看做是此配置的編號
    __u8  iConfiguration;      // 此配置對應(yīng)的字符串描述符的索引值
    __u8  bmAttributes;        // 此配置的特征。bit7必須為1,bit6:self powered. bit5:can wakeup. bit4:battery powered.
    __u8  bMaxPower;           // 表示此設(shè)備需要的最大電流,以2mA為單位
} __attribute__ ((packed));

在內(nèi)核usb代碼中,struct usb_device結(jié)構(gòu)體的config成員表示設(shè)備支持的所有配置,actconfig成員表示當(dāng)前激活的配置。在sysfs中,configuration(若不為空)就是當(dāng)前激活的配置的名稱(對應(yīng)配置描述符中的iConfiguration)。而sysfs中的bConfigurationValue與配置描述符中的bConfigurationValue對應(yīng),讀回就是當(dāng)前激活的配置的編號,寫入就是激活指定編號的配置。

2.3 接口描述符

struct usb_interface_descriptor {
    __u8  bLength;            // 9
    __u8  bDescriptorType;    // USB_DT_INTERFACE, 0x04
    __u8  bInterfaceNumber;   // 接口編號(zero-base)
    __u8  bAlternateSetting;  // 設(shè)置(setting)編號(zero-base)
    __u8  bNumEndpoints;      // 包含的端點(diǎn)數(shù)目(端點(diǎn)0不包含在內(nèi))
    __u8  bInterfaceClass;    // 見第3節(jié),“類別(Class)和協(xié)議(Protocol)”
    __u8  bInterfaceSubClass;
    __u8  bInterfaceProtocol;
    __u8  iInterface;         // 此接口對應(yīng)的字符串描述符的索引值
} __attribute__ ((packed));

有一種可能,配置中包含的接口的數(shù)目為1,但有多個接口描述符,應(yīng)該就是一個接口的不同設(shè)置(setting),因此有相同的接口編號(bInterfaceNumber),不同的設(shè)置(setting)(bAlternateSetting)編號。

2.4 端點(diǎn)描述符

struct usb_endpoint_descriptor {
    __u8  bLength;          // 7,9
    __u8  bDescriptorType;  // USB_DT_ENDPOINT, 0x05
    __u8  bEndpointAddress; // bit0~3表示端點(diǎn)編號,bit8表示端點(diǎn)方向
    __u8  bmAttributes;     // 端點(diǎn)屬性
    __le16 wMaxPacketSize;  // 端點(diǎn)一次可以處理的最大字節(jié)數(shù)
    __u8  bInterval;        // 輪詢時間間隔
    __u8  bRefresh;         // 音頻相關(guān)
    __u8  bSynchAddress;    // 音頻相關(guān)
} __attribute__ ((packed));
  1. 類別(Class)和協(xié)議(Protocol)

類別(Class)是針對設(shè)備和接口定義的,有一些類別(Class)僅針對設(shè)備,有一些類別(Class)僅針對接口,還有一些類別(Class)對設(shè)備和接口都有效。如下圖所示:


class.jpg

而子類別(SubClass)和協(xié)議(Protocol)就根據(jù)類別(Class)的不同而不同了。
以常見的HID為例,它對應(yīng)的子類別(SubClass)和協(xié)議(Protocol)如下圖所示:


hid.jpg

而Mass Storage對應(yīng)的則是:
mass.jpg

上述信息參考如下網(wǎng)址:
https://www.usb.org/defined-class-codes
https://www.usb.org/sites/default/files/hid1_11.pdf
https://www.usb.org/sites/default/files/Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf
更多信息,可以在下面的網(wǎng)址中搜索相關(guān)文檔:
https://www.usb.org/documents?search=spec&items_per_page=50

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容