STM32學習筆記之USB虛擬串列埠描述符簡介
Descriptor即描述符,是一個完整的資料結構,可以通過C語言等程式設計實現,並存儲在USB裝置中,用於描述一個USB裝置的所有屬性,USB主機是通過一系列命令來要求裝置傳送這些資訊的。它的作用就是通過如問答節中的命令***作來給主機傳遞資訊,從而讓主機知道裝置具有什麼功能、屬於哪一類裝置、要佔用多少頻寬、使用哪類傳輸方式及資料量的大小,只有主機確定了這些資訊之後,裝置才能真正開始工作,所以描述符也是十分重要的部分,要好好掌握。標準的描述符有5種,USB為這些描述符定義了編號:
1——裝置描述符
2——配置描述符
3——字元描述符
4——介面描述符
5——端點描述符
上面的描述符之間有一定的關係,一個裝置只有一個裝置描述符,而一個裝置描述符可以包含多個配置描述符,而一個配置描述符可以包含多個介面描述符,一個介面使用了幾個端點,就有幾個端點描述符。這間描述符是用一定的欄位構成的,分別如下說明:
1、裝置描述符
struct _DEVICE_DEscriptOR_STRUCT
{
BYTE bLength; //裝置描述符的位元組數大小,為0x12
BYTE bDescriptorType; //描述符型別編號,為0x01
WORD bcdUSB; //USB版本號
BYTE bDeviceClass; //USB分配的裝置類程式碼,0x01~0xfe為標準裝置類,0xff為廠商自定義型別
//0x00不是在裝置描述符中定義的,如HID
BYTE bDeviceSubClass; //usb分配的子類程式碼,同上,值由USB規定和分配的
BYTE bDeviceProtocl; //USB分配的裝置協議程式碼,同上
BYTE bMaxPacketSize0; //端點0的最大包的大小
WORD idVendor; //廠商編號
WORD idProduct; //產品編號
WORD bcdDevice; //裝置出廠編號
BYTE iManufacturer; //描述廠商字串的索引
BYTE iProduct; //描述產品字串的索引
BYTE iSerialNumber; //描述裝置序列號字串的索引
BYTE bNumConfiguration; //可能的配置數量
}
2、配置描述符
struct _CONFIGURATION_DEscriptOR_STRUCT
{
BYTE bLength; //裝置描述符的位元組數大小,為0x12
BYTE bDescriptorType; //描述符型別編號,為0x01
WORD wTotalLength; //配置所返回的所有數量的大小
BYTE bNumInterface; //此配置所支援的介面數量
BYTE bConfigurationVale; //Set_Configuration命令需要的引數值
BYTE iConfiguration; //描述該配置的字串的索引值
BYTE bmAttribute; //供電模式的選擇
BYTE MaxPower; //裝置從匯流排提取的最大電流
}
3、字元描述符
struct _STRING_DEscriptOR_STRUCT
{
BYTE bLength; //裝置描述符的位元組數大小,為0x12
BYTE bDescriptorType; //描述符型別編號,為0x01
BYTE SomeDescriptor[36]; //UNICODE編碼的字串
}
4、介面描述符
struct _INTERFACE_DEscriptOR_STRUCT
{
BYTE bLength; //裝置描述符的位元組數大小,為0x12
BYTE bDescriptorType; //描述符型別編號,為0x01
BYTE bInterfaceNunber; //介面的編號
BYTE bAlternateSetting;//備用的介面描述符編號
BYTE bNumEndpoints; //該介面使用端點數,不包括端點0
BYTE bInterfaceClass; //介面型別
BYTE bInterfaceSubClass;//介面子型別
BYTE bInterfaceProtocol;//介面所遵循的協議
BYTE iInterface; //描述該介面的字串索引值
}
5、端點描述符
struct _ENDPOIN_DEscriptOR_STRUCT
{
BYTE bLength; //裝置描述符的位元組數大小,為0x12
BYTE bDescriptorType; //描述符型別編號,為0x01
BYTE bEndpointAddress; //端點地址及輸入輸出屬性
BYTE bmAttribute; //端點的傳輸型別屬性
WORD wMaxPacketSize; //端點收、發的最大包的大小
BYTE bInterval; //主機查詢端點的時間間隔
}
具體分析如下:
1、描述裝置型別Device Descriptor
包含了裝置名稱,類別,生產廠家等等資訊,通過得到的這些資訊Host會去找到合適的裝置驅動程式在主機上載入驅動。
/* USB Standard Device Descriptor */
const u8 Virtual_Com_Port_DeviceDescriptor[] =
{
0x12, /* bLength */ //USB裝置描述符的總長度固定為18個位元組,因此為12H
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ //USB裝置描述符的型別值,固定為01H
0x00, //USB遵循的規範版本號,USB2.0; 0xXXYZ,XX為主版本號,Y為次版本號,Z為子次版本號
0x02, /* bcdUSB = 2.00 */
0x02, /* bDeviceClass: CDC */ //USB所遵循的標準裝置類。0表示裝置的介面相互獨立,分別屬於不同的裝置類;
//1~FEH之間表示USB協議中定義的某個類。03H表示HID類,02H表示CDC類。
//FFH表示供應商自定義的裝置類
0x00, /* bDeviceSubClass */ //USB裝置所屬的標準裝置子類。對於顯示裝置類(04H),包含3個子類,
//子類程式碼01H表示CRT顯示器,02H表示平面顯示器,03H表示3D顯示器。
//bDeviceClass為0時,該值為0;該值為FFH時,表示供應商自定義的裝置子類
0x00, /* bDeviceProtocol */ //採用的裝置類協議。該值為FFH時表示裝置類協議由供應商自定義
0x40, /* bMaxPacketSize0 */ //端點0所支援最大資料包長度(位元組),低速為8,全速為8,16,32或64,高速為64
0x83, //裝置供應商id,使主機為其載入合適驅動
0x04, /* idVendor = 0x0483 */
0x40, //產品id,用於區分不同的usb裝置
0x57, /* idProduct = 0x7540 */
0x00, //裝置版本號,幫助主機載入合適驅動
0x01, /* bcdDevice = 1.00 */
1, /* Index of string descriptor describing manufacturer */ //若沒有,可為0
2, /* Index of string descriptor describing product */ //若沒有,可為0
3, /* Index of string descriptor describing the device's serial number */ //若沒有,可為0
0x01 /* bNumConfigurations */ //USB裝置所支援的配置數
};
2、配置描述符Config Descriptor
包含了介面型別,最大功耗(電流),供電方式等等資訊,事實上這個配置描述項不僅僅是剛才說的這些作用,更多地,它需要通知主機裝置所使用的ENDpoint的情況,使用的類驅動型別,等等資訊
const u8 Virtual_Com_Port_ConfigDescriptor[] =
{
/*Configuation Descriptor*/
0x09, /* bLength: Configuation Descriptor size */ //配置描述符的長度,固定為9位元組,09H
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */ //配置描述符型別,固定位02H
VIRTUAL_COM_PORT_SIZ_CONFIG_DESC, /* wTotalLength:no of returned bytes */ //配置資訊總長度,配置描述符、介面描述符、端點描述符長度總和
0x00,
0x02, /* bNumInterfaces: 2 interface */ //所支援的介面數, 最小值為1
0x01, /* bConfigurationValue: Configuration value */ //USB裝置的配置值
0x00, /* iConfiguration: Index of string descriptor describing the configuration */ //字串描述符索引,若沒有,可為0
0xC0, /* bmAttributes: self powered */ //配置特性,可按位定址,第六位置1表示用匯流排電源,第五位置1表示支援遠端喚醒,其他欄位保留
//一般0~4位置0,第7位置1
0x00, /* MaxPower 0 mA */ //USB裝置執行時所支援的最大電流,2mA為單位
/*Interface Descriptor*/
0x09, /* bLength: Interface Descriptor size */ //介面描述符長度,固定為9位元組,09H
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */ //介面描述符的型別值,固定位04H
/* Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */ //USB介面的介面號
0x00, /* bAlternateSetting: Alternate setting */ //USB介面的可替換設定值
0x01, /* bNumEndpoints: One endpoints used */ //USB介面所使用的介面總數
0x02, /* bInterfaceClass: Communication Interface Class */ //USB介面所屬的裝置類,1~FEH表示某個裝置類;FFH表示供應商自定義
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */ //介面所採用的裝置類協議
0x00, /* iInterface: */ //USB介面字串描述符的索引值
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*Call Managment Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface: 1 */
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/*Union Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 2 Descriptor*/ //端點描述符長度固定為7位元組,07H
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x82, /* bEndpointAddress: (IN2) */
0x03, /* bmAttributes: Interrupt */
VIRTUAL_COM_PORT_INT_SIZE, /* wMaxPacketSize: */
0x00,
0xFF, /* bInterval: */
/*Data class interface descriptor*/
0x09, /* bLength: Endpoint Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
/*Endpoint 3 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x03, /* bEndpointAddress: (OUT3) */
0x02, /* bmAttributes: Bulk */
VIRTUAL_COM_PORT_DATA_SIZE, /* wMaxPacketSize: */
0x00,
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint 1 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x81, /* bEndpointAddress: (IN1) */
0x02, /* bmAttributes: Bulk */
VIRTUAL_COM_PORT_DATA_SIZE, /* wMaxPacketSize: */
0x00,
0x00 /* bInterval */
};
由於上面我們在設定了使用USB CDC類,我們就要按照CDC的規則來設定,
按照CDC協議的內容FunctionalDescriptor只包含如下幾個:
Header Functional Descriptor:
Abstract Control Management functional Descriptor :定義了Communication Class Interface所支援的命令集合。具 體到下面的內容為:裝置不支援Send_Break,Set_line_Coding,Set_Control_Line_State,Get_Line_Coding, Set_Comm_Feature,Clear_Comm_Feature,Get_Comm_Feature請求和Serial_State,Network_Connection消
息,也就是說禁用所有可選Abstract Control Model*的訊息和請求,緊緊保留了必需的 SEND_ENCAPSULATED_COMMAND,Get_ENCAPSULATED_COMMAND請求和RESPONSE_AVAILABLE訊息。
Call Manageament Functional Descriptor:該描述項定義了相關管理呼叫的約束和方式,裝置傳送接收管理資訊使用通訊類介面,裝置不自己呼叫管理功能。
UNION function descriptor:就是起到聯絡各個獨立的Interface,描述其之間的關係的作用。