ガレスタさんのDIY日記

電子回路、Web、組み込み、自作エフェクターを語るblog

自分用メモ IAD

Interface Association Descriptor

USB2.0により増えた規格。
それまでは複合デバイスを作る際どれがどのインターフェイスがわからず無法地帯だったらしい
そこでIAD増やして明示的にした

結局どゆことかというと
USBデバイスではコンフィグに複数のInterfaceを持つことができる。
そのときにどれがどのファンクションに対応するかわからんのでそいつの補足をする機能
f:id:gsmcustomeffects:20170621022247p:plain

でぃすくりぷたと兼ねて説明

バイスディスクリプタ欄にあらかじめIADであると明示することで最初のGetDesicriptorの段階でホスト側にIADですよ~と伝える
そうするとホストはInterfaceが複数いる何かがつながったな?やれやれと理解するわけだ

f:id:gsmcustomeffects:20170621023624p:plain

んで肝心なInterface Association Descriptorはこういう構成

f:id:gsmcustomeffects:20170621025130p:plain


あとは

コンフィグ→IAD→インターフェイス→その他→エンドポイント

的な感じでディスクリプタを記述していく

STでDualCOMを実現するときのディスクリプタはこんな感じ

device descriptor

__ALIGN_BEGIN uint8_t USBD_HS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = // Virtual_Com_Port_DeviceDescriptor
  {
    0x12,                       /* 00 bLength */
    USB_DESC_TYPE_DEVICE,       /* 01 bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
    0x01,                       /* 02 bcdUSB */ /* changed to USB version 2.01
                                               in order to support LPM L1 suspend
                                               resume test of USBCV3.0*/
#else
    0x00,                       /* 02 bcdUSB */
#endif

    0x02,						/* 03 */
    0xEF,                       /* 04 bDeviceClass IAD*/
    0x02,                       /* 05 bDeviceSubClass*/
    0x01,                       /* 06 bDeviceProtocol IAD*/
    USB_MAX_EP0_SIZE,           /* 07 bMaxPacketSize*/
    LOBYTE(USBD_VID),           /* 08 idVendor*/
    HIBYTE(USBD_VID),           /* 09 idVendor*/
    LOBYTE(USBD_PID_HS),        /* 10 idVendor*/
    HIBYTE(USBD_PID_HS),        /* 11 idVendor*/
    0x00,                       /* 12 bcdDevice rel. 2.00*/
    0x02,						/* 13 */
    USBD_IDX_MFC_STR,           /* 14 Index of manufacturer  string*/
    USBD_IDX_PRODUCT_STR,       /* 15 Index of product string*/
    USBD_IDX_SERIAL_STR,        /* 16 Index of serial number string*/
    USBD_MAX_NUM_CONFIGURATION  /* 17 bNumConfigurations*/
  } ;

config descriptorおよび他の記述

__ALIGN_BEGIN uint8_t USBD_IAD_CfgHSDesc[USB_IAD_CONFIG_DESC_SIZ] __ALIGN_END =
{
	//Configuation Descriptor
	0x09,								// 00 bLength: Configuation Descriptor size
	USB_DESC_TYPE_CONFIGURATION,		// 01 bDescriptorType: Configuration
	USB_IAD_CONFIG_DESC_SIZ,			// 02 wTotalLength:no of returned bytes
	0x00,								// 03
	0x04,								// 04 bNumInterfaces: 4 interface
	0x01,								// 05 bConfigurationValue: Configuration value
	0x00,								// 06 iConfiguration: Index of string descriptor describing the configuration
	0xC0,								// 07 bmAttributes: self powered
	0x32,								// 08 MaxPower 100 mA

	// IAD 1 -> CDC1
	0x08,// 09 bLength: Interface Descriptor size
	0x0B,								// 10 bDescriptorType: IAD
	0x00,								// 11 bFirstInterface
	0x02,								// 12 bInterfaceCount
	0x02,								// 13 bFunctionClass: CDC
	0x02,								// 14 bFunctionSubClass
	0x01,								// 15 bFunctionProtocol
	0x02,								// 16 iFunction

	//Interface Descriptor
	0x09,								// 17 bLength: Interface Descriptor size
	USB_DESC_TYPE_INTERFACE,			// 18 bDescriptorType: Interface
	// Interface descriptor type
	0x00,								// 19 bInterfaceNumber: Number of Interface
	0x00,								// 20 bAlternateSetting: Alternate setting
	0x01,								// 21 bNumEndpoints: One endpoints used
	0x02,								// 22 bInterfaceClass: Communication Interface Class
	0x02,								// 23 bInterfaceSubClass: Abstract Control Model
	0x01,								// 24 bInterfaceProtocol: Common AT commands
	0x00,								// 25 iInterface:

	//Header Functional Descriptor
	0x05,								// 26 bLength: Endpoint Descriptor size
	0x24,								// 27 bDescriptorType: CS_INTERFACE
	0x00,								// 28 bDescriptorSubtype: Header Func Desc
	0x10,								// 29 bcdIAD: spec release number
	0x01,								// 30

	//Call Managment Functional Descriptor
	0x05,								// 31 bFunctionLength
	0x24,								// 32 bDescriptorType: CS_INTERFACE
	0x01,								// 33 bDescriptorSubtype: Call Management Func Desc
	0x00,								// 34 bmCapabilities: D0+D1
	0x01,								// 35 bDataInterface: 1

	//ACM CDC1 Functional Descriptor
	0x04,								// 36 bFunctionLength
	0x24,								// 37 bDescriptorType: CS_INTERFACE
	0x02,								// 38 bDescriptorSubtype: Abstract Control Management desc
	0x02,								// 39 bmCapabilities

	//Union Functional Descriptor
	0x05,								// 40 bFunctionLength
	0x24,								// 41 bDescriptorType: CS_INTERFACE
	0x06,								// 42 bDescriptorSubtype: Union func desc
	0x00,								// 43 bMasterInterface: Communication class interface
	0x01,								// 44 bSlaveInterface0: Data Class Interface

	//Endpoint CDC1 CMD Descriptor
	0x07,								// 45 bLength: Endpoint Descriptor size
	USB_DESC_TYPE_ENDPOINT,				// 46 bDescriptorType: Endpoint
	IAD_CDC1_CMD_EP,					// 47 bEndpointAddress: (IN2)
	0x03,								// 48 bmAttributes: Interrupt
	LOBYTE(IAD_CDC_CMD_PACKET_SIZE),	// 49 wMaxPacketSize:
	HIBYTE(IAD_CDC_CMD_PACKET_SIZE),	// 50
	0xFF,								// 51 bInterval:
	//---------------------------------------------------------------------------

	//Data class interface descriptor
	0x09,								// 52 bLength: Endpoint Descriptor size
	USB_DESC_TYPE_INTERFACE,			// 53 bDescriptorType:
	0x01,								// 54 bInterfaceNumber: Number of Interface
	0x00,								// 55 bAlternateSetting: Alternate setting
	0x02,								// 56 bNumEndpoints: Two endpoints used
	0x0A,								// 57 bInterfaceClass: CDC
	0x00,								// 58 bInterfaceSubClass:
	0x00,								// 59 bInterfaceProtocol:
	0x00,								// 60 iInterface:

	//Endpoint CDC1 OUT Descriptor
	0x07,								// 61 bLength: Endpoint Descriptor size
	USB_DESC_TYPE_ENDPOINT,				// 62 bDescriptorType: Endpoint
	IAD_CDC1_OUT_EP,					// 63 bEndpointAddress: (OUT1)
	0x02,								// 64 bmAttributes: Bulk
	LOBYTE(IAD_DATA_HS_MAX_PACKET_SIZE),// 65 wMaxPacketSize:
	HIBYTE(IAD_DATA_HS_MAX_PACKET_SIZE),// 66
	0x00,								// 67 bInterval: ignore for Bulk transfer

	//Endpoint CDC1 IN Descriptor
	0x07,								// 68 bLength: Endpoint Descriptor size
	USB_DESC_TYPE_ENDPOINT,				// 69 bDescriptorType: Endpoint
	IAD_CDC1_IN_EP,						// 70 bEndpointAddress: (IN1)
	0x02,								// 71 bmAttributes: Bulk
	LOBYTE(IAD_DATA_HS_MAX_PACKET_SIZE),// 72 wMaxPacketSize:
	HIBYTE(IAD_DATA_HS_MAX_PACKET_SIZE),// 73
	0x00,								// 74 bInterval

	// IAD 2 -> CDC2
	0x08,// 75 bLength: Interface Descriptor size
	0x0B,								// 76 bDescriptorType: IAD
	0x02,								// 77 bFirstInterface
	0x02,								// 78 bInterfaceCount
	0x02,								// 79 bFunctionClass: CDC
	0x02,								// 80 bFunctionSubClass
	0x01,								// 81 bFunctionProtocol
	0x02,								// 82 iFunction

	//Interface Descriptor
	0x09,// 83 bLength: Interface Descriptor size
	USB_DESC_TYPE_INTERFACE,			// 84 bDescriptorType: Interface
	// Interface descriptor type
	0x02,								// 85 bInterfaceNumber: Number of Interface
	0x00,								// 86 bAlternateSetting: Alternate setting
	0x01,								// 87 bNumEndpoints: One endpoints used
	0x02,								// 88 bInterfaceClass: Communication Interface Class
	0x02,								// 89 bInterfaceSubClass: Abstract Control Model
	0x01,								// 90 bInterfaceProtocol: Common AT commands
	0x00,								// 91 iInterface:

	//Header Functional Descriptor
	0x05,								// 92 bLength: Endpoint Descriptor size
	0x24,								// 93 bDescriptorType: CS_INTERFACE
	0x00,								// 94 bDescriptorSubtype: Header Func Desc
	0x10,								// 95 bcdCDC: spec release number
	0x01,								// 96

	//Call Managment Functional Descriptor
	0x05,								// 97 bFunctionLength
	0x24,								// 98 bDescriptorType: CS_INTERFACE
	0x01,								// 99 bDescriptorSubtype: Call Management Func Desc
	0x00,								// 100 bmCapabilities: D0+D1
	0x03,								// 101 !! bDataInterface:

	//ACM CDC2 Functional Descriptor
	0x04,								// 102 bFunctionLength
	0x24,								// 103 bDescriptorType: CS_INTERFACE
	0x02,								// 104 bDescriptorSubtype: Abstract Control Management desc
	0x02,								// 105 bmCapabilities

	//Union Functional Descriptor
	0x05,								// 106 bFunctionLength
	0x24,								// 107 bDescriptorType: CS_INTERFACE
	0x06,								// 108 bDescriptorSubtype: Union func desc
	0x02,								// 109 !! bMasterInterface: Communication class interface
	0x03,								// 110 !! bSlaveInterface0: Data Class Interface

	//Endpoint CDC2 CMD Descriptor
	0x07,								// 111 bLength: Endpoint Descriptor size
	USB_DESC_TYPE_ENDPOINT,				// 112 bDescriptorType: Endpoint
	IAD_CDC2_CMD_EP,					// 113 bEndpointAddress: (IN4)
	0x03,								// 114 bmAttributes: Interrupt
	LOBYTE(IAD_CDC_CMD_PACKET_SIZE),	// 115 wMaxPacketSize:
	HIBYTE(IAD_CDC_CMD_PACKET_SIZE),	// 116
	0xFF,								// 117 bInterval:
	//---------------------------------------------------------------------------

	//Data class interface descriptor
	0x09,								// 118 bLength: Endpoint Descriptor size
	USB_DESC_TYPE_INTERFACE,			// 119 bDescriptorType:
	0x03,								// 120 bInterfaceNumber: Number of Interface
	0x00,								// 121 bAlternateSetting: Alternate setting
	0x02,								// 122 bNumEndpoints: Two endpoints used
	0x0A,								// 123 bInterfaceClass: CDC
	0x00,								// 124 bInterfaceSubClass:
	0x00,								// 125 bInterfaceProtocol:
	0x00,								// 126 iInterface:

	//Endpoint CDC2 OUT Descriptor
	0x07,								// 127 bLength: Endpoint Descriptor size
	USB_DESC_TYPE_ENDPOINT,				// 128 bDescriptorType: Endpoint
	IAD_CDC2_OUT_EP,					// 129 bEndpointAddress: (OUT3)
	0x02,								// 130 bmAttributes: Bulk
	LOBYTE(IAD_DATA_HS_MAX_PACKET_SIZE),// 131 wMaxPacketSize:
	HIBYTE(IAD_DATA_HS_MAX_PACKET_SIZE),// 132
	0x00,								// 133 bInterval: ignore for Bulk transfer

	//Endpoint CDC2 IN Descriptor
	0x07,								// 134 bLength: Endpoint Descriptor size
	USB_DESC_TYPE_ENDPOINT,				// 135 bDescriptorType: Endpoint
	IAD_CDC2_IN_EP,						// 136 bEndpointAddress: (IN3)
	0x02,								// 137 bmAttributes: Bulk
	LOBYTE(IAD_DATA_HS_MAX_PACKET_SIZE),// 138 wMaxPacketSize:
	HIBYTE(IAD_DATA_HS_MAX_PACKET_SIZE),// 139
	0x00,								// 140 bInterval
};

恥ずかしい余談

ちなみにCDCはInterfaceがもともと二つある。
DATAクラス、CDCクラスがそれにあたる。
なのでCDCが2つあるとどっちがどっちのDATAやねん?という問題が発生する。
それを解決するのがIAD1とIAD2なわけ
CDCが2つ→DATAクラス2個、CDCクラス2個→よって総インターフェイス数は4つ(最初CDC2つなら2やん?と勘違いしてた僕
なので下記の記述が4になってる
f:id:gsmcustomeffects:20170621030224p:plain

まとめ

f:id:gsmcustomeffects:20170621030336p:plain

STM32のUSBCDCでMicroShellを動かす

前回まででUSBCDC(コミュニケーションデバイスクラス)でVCP(VirtualCOMPort)の動作は確認できたので今回はこれにMicroShellを使える状態していく作業になります。
CDCのやり方はこの記事みてくれ
gsmcustomeffects.hatenablog.com

やることは

  • 1文字送受信APIの準備
  • 受信バッファサイズの設定
続きを読む

Eclipseでファイル比較を使う

ここ最近USB系やっていてサンプルを参考にしつつ書くことが多い。
その中で2ファイル中の差異を比較できたら便利だと思って比較機能を使ってみることにした。

やり方はこういう感じでファイルをCtrl推しながら選んで右クリックで相互を選ぶ(当方の環境はAtollicTrueStudio

f:id:gsmcustomeffects:20170618012111p:plain

そうするとこのように差異が表示される。

この例ではUSBフルスピードとUSBハイスピードのディスクリプタを示している。

f:id:gsmcustomeffects:20170618012939p:plain

まとめ

二つのファイルの比較ができた。
今後はもっとEclipseの機能をフル活用していきたい

Eclipseでファイル横断サーチする

僕はARMマイコン開発でもっぱらEclipseベースIDEを使用するわけなんですがその途中でワード検索よく多用します。
Ctrl+Fの検索機能は一般的なサーチです。

f:id:gsmcustomeffects:20170617013200p:plain

しかしこれではファイル内しか検索できませんので単一ソースの確認しかできません
最近のマイコンの場合Defineマクロが多用されていて余裕で外部から呼び出したりをして複雑怪奇です。

そういった場合Ctrl+Hのサーチが便利です。


f:id:gsmcustomeffects:20170617013412p:plain

これを使うことによりファイルをまたいだ検索ができます

f:id:gsmcustomeffects:20170617013506p:plain

自分用メモ デバイスディスクリプタ

バイスディスクリプタディスクリプタ階層の一番上に属する。

一応書いておくと以下のような感じだ
┏デバイスディスクリプタ
 ┝コンフィグレーションディスクリプタ
  ┝インターフェイスディスクリプタ
   ┝エンドポイントディスクリプタ

役割としては主にVID,PIDとか一般情報を書くディスクリプタである。
Universal Serial Bus Specification9.6.1のデバイスディスクリプタの項目に説明があるので詳しく知りたい方はここを見てくれ

http://sdphca.ucsd.edu/lab_equip_manuals/usb_20.pdf(ここの290ページ辺り)
STの実際の記述と見比べてみると・・・・

__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
  {
    0x12,                       /*bLength */
    USB_DESC_TYPE_DEVICE,       /*bDescriptorType*/
#if (USBD_LPM_ENABLED == 1)
    0x01,                       /*bcdUSB */ /* changed to USB version 2.01 
                                               in order to support LPM L1 suspend
                                               resume test of USBCV3.0*/
#else  
    0x00,                       /* bcdUSB */
#endif
    0x02,
    0x02,                        /*bDeviceClass*/
    0x02,                       /*bDeviceSubClass*/
    0x00,                       /*bDeviceProtocol*/
    USB_MAX_EP0_SIZE,          /*bMaxPacketSize*/
    LOBYTE(USBD_VID),           /*idVendor*/
    HIBYTE(USBD_VID),           /*idVendor*/
    LOBYTE(USBD_PID_FS),           /*idVendor*/
    HIBYTE(USBD_PID_FS),           /*idVendor*/
    0x00,                       /*bcdDevice rel. 2.00*/
    0x02,
    USBD_IDX_MFC_STR,           /*Index of manufacturer  string*/
    USBD_IDX_PRODUCT_STR,       /*Index of product string*/
    USBD_IDX_SERIAL_STR,        /*Index of serial number string*/
    USBD_MAX_NUM_CONFIGURATION  /*bNumConfigurations*/
  } ; 
Field Offset Size 詳細
bLength 0 1 ディスクリプタの全体長。デバイスディスクリプタは 18(0x12)Byte
bDescriptorType 1 1 ディスクリプタの種別番号。DEVICE は 1。
bcdUSB 2 2 USB のバージョン(BCD)。
bDeviceClass 4 1 クラス番号 (USBクラス)。0x0 と 0xFF 以外は USB-IF が予約している。
bDeviceSubClass 5 1 サブクラス番号。0x0 と 0xFF 以外は クラス番号に依存する。
bDeviceProtocol 6 1 プロトコル番号。0x0 と 0xFF 以外は クラス、サブクラス番号に依存する。
bMaxPacketSize0 7 1 エンドポイント0の最大パケットサイズ(Byte)。速度別に規定がある。
idVendor 8 2 ベンダID(VID)。USB-IF より ID を発行(有償)してもらう必要有り。
idProduct 10 2 プロダクトID(PID)。ベンダー各社がプロダクト毎に ID を自由に振りふれる。
bcdDevice 12 2 バイスのバージョン番号(BCD)。
iManufacturer 14 1 製造者の ストリングディスクリプタ の Index 番号。0の場合、指定無し。
iProduct 15 1 Product の ストリングディスクリプタ の Index 番号。0の場合、指定無し。
iSerialNumber 16 1 シリアルナンバーのストリングディスクリプタの Index 番号。0の場合、指定無し。複数接続を前提とするならば指定が必要。
bNumConfigurations 17 1 コンフィグレーションディスクリプタの個数。

※日本語訳はおなかすいたWiki様より借用
デバイスディスクリプタ - おなかすいたWiki!

表よりわかるがデバイスディスクリプタは18byte固定となるのでここら辺はソースを読み進めやすいはず。
またbDeviceClassとかをよく見てソースコード読み進めていくと理解しやすい。
ここが0xEFとかになってたらIADと呼ばれる一個のコンフィグに複数のインターフェイスを持つものになっていることが多いのでここの情報はしっかり把握しておくこと。
自分が確認したところCDCのサンプルではSTが0x02,LPCが0xEFになっていた。



なので次回は以下の点を勉強して行きたいと思う

自分用メモ コンフィグレーションディスクリプタ

前回CDCやったのでそれの補足

ディスクリプタは以下のような構成になっている。

┏デバイスディスクリプタ
 ┝コンフィグレーションディスクリプタ
  ┝インターフェイスディスクリプタ
   ┝エンドポイントディスクリプタ

バイスディスクリプタについては前回やったので今回はSTM32のCDCの中のコンフィグとインターフェイス及びエンドポイントを見ていく

コンフィグレーションディスクリプタ

STのsampleの例ではusbd_cdc.cUSBD_CDC_CfgHSDesc冒頭9byteがそれにあたる。

__ALIGN_BEGIN uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
  /*Configuration Descriptor*/
  0x09,   /* bLength: Configuration Descriptor size */
  USB_DESC_TYPE_CONFIGURATION,      /* bDescriptorType: Configuration 0x02 */
  USB_CDC_CONFIG_DESC_SIZ,                /* wTotalLength:no of returned bytes */
  0x00,
  0x02,   /* bNumInterfaces: 2 interface */
  0x01,   /* bConfigurationValue: Configuration value */
  0x00,   /* iConfiguration: Index of string descriptor describing the configuration */
  0xC0,   /* bmAttributes: self powered */
  0x32,   /* MaxPower 0 mA */
 以下続く
Field Offset Size 詳細
bLength 0 1 Descriptor の全体長。
bDescriptorType 1 1 Descriptor Types
wTotalLength 2 2 当該、および従属ディスクリプタの全長
bNumInterface 4 1 インターフェイスディスクリプタの個数。
bConfigurationValue 5 1 Configuration 番号。SET_CONFIGURATION時のID。
iConfiguration 6 1 Configuration のストリングディスクリプタ の Index 番号。0の場合、指定無し
bmAttributes 7 1 bit 7:予約(1)。
bit 6:Self Power(0/1)
bit 5:Remote Wakeup機能(0/1)。
bit 4-0:予約(0)。
bMaxPower 8 1 必要とするバスからの電流の1/2(mA)。

bLengthは9byte固定
bDescriptorTypeはCONFIGなので0x02
wTotalLengthは2byte分あるのでUSB_CDC_CONFIG_DESC_SIZ,0x00になっている。USB_CDC_CONFIG_DESC_SIZは本プログラムの例では67となっているが自身で作る場合はこの後続くディスクリプタを含めた大きさを書く。

参考文献

http://sdphca.ucsd.edu/lab_equip_manuals/usb_20.pdf