macOSからPi Picoを使う - その17 [Pi Pico]
前回tusb.hを読んでみて、必要なUSB classのヘッダしか読み込まれないし、不要なclass用のコードはリンクされなくて、その呼び出しは関数ポインタを並べた構造体を経由して行われることがわかった。ちょっと遠回りのような気もするけど、なるべくコードサイズを抑えるための配慮だと思われる。組み込みではこうするのが普通なのかな。そのへんはよくわからない。
今日はUSB descriptorをTinyUSBではどう扱うかを見ていく....
このあとUSBの規格にかかわる部分が出てくる。非常に細かいところもあって、それはUSBの規格書にまで遡らないといけない。USBの規格書はusb.orgの本家サイトからアクセスできるけど、膨大な量があってどこから見ればいいのかよくわからなくなる。ダイジェストしてくれているところもいくつかあるけど、ダイジェストしすぎてプログラミングには不十分だったりする。誰か過不足のないのを作ってくれないだろうか。
に定義がある。
となっていて、いろんなところで解説してくれているdevice descriptorのフィールド名までそのままである。まあ、変える必要もないけど。
ついでにここでそれぞれのフィールドの意味を備忘録として書いておく。すぐ忘れるし。
フィールド名の最初の文字は
を表している。
この構造体のメンバを埋めるヘルパ関数でもあるか、と思って探したけどほんのちょっとだけ。自分でUSBの仕様に従って埋めていくしかない。いちおうこのtusb_types.hのファイルの初めの方に読みやすく文字でdefineされた定数がenumであるので、実際にdescriptorを書くときはその定数を使うのがいい。
となっている。これもフィールドの意味を書いておく。
bmAttributesはビットフィールドで、
となっている。
device/subd.hに設定用の簡単なmacroがある。
また、この定義の後にclass別のmacroもある。
今日はUSB descriptorをTinyUSBではどう扱うかを見ていく....
15.3 TinyUSBのdescriptor
だいたいの構造はわかったとしよう。つまり- tusb_config.hにどのクラスに対応したいかなどを書く
- main.c(名前はなんでもいい)にそのクラスの読み書き関数を呼ぶことで実体を書く
- 全体をリンクする
このあとUSBの規格にかかわる部分が出てくる。非常に細かいところもあって、それはUSBの規格書にまで遡らないといけない。USBの規格書はusb.orgの本家サイトからアクセスできるけど、膨大な量があってどこから見ればいいのかよくわからなくなる。ダイジェストしてくれているところもいくつかあるけど、ダイジェストしすぎてプログラミングには不十分だったりする。誰か過不足のないのを作ってくれないだろうか。
15.3.1 device descriptor
USBデバイスとして動作させるためにはまずdevice descriptorを書かなければいけないはずである。TinyUSBではどうなってるかというと、src/common/tusb_types.h
/// USB Device Descriptor typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< DEVICE Descriptor Type. uint16_t bcdUSB ; ///< BUSB Specification Release Number in B uint8_t bDeviceClass ; ///< Class code (assigned by the USB-IF). uint8_t bDeviceSubClass ; ///< Subclass code (assigned by the USB-IF). uint8_t bDeviceProtocol ; ///< Protocol code (assigned by the USB-IF). uint8_t bMaxPacketSize0 ; ///< Maximum packet size for endpoint zero ( uint16_t idVendor ; ///< Vendor ID (assigned by the USB-IF). uint16_t idProduct ; ///< Product ID (assigned by the manufacturer). uint16_t bcdDevice ; ///< Device release number in binary-coded uint8_t iManufacturer ; ///< Index of string descriptor describing manu uint8_t iProduct ; ///< Index of string descriptor describing prod uint8_t iSerialNumber ; ///< Index of string descriptor describing uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t;
ついでにここでそれぞれのフィールドの意味を備忘録として書いておく。すぐ忘れるし。
フィールド名の最初の文字は
b: | 1バイト |
w: | 2バイト |
bm: | 1バイトのビットマップ |
bcd: | Binary Coded Decimal、4ビットで10進一桁を表す数値 |
i: | インデクス値 |
を表している。
Table 1: device descriptorの意味
bLength | descriptorのバイト数。Device descriptorは18バイト |
bDescriptorType | 何のdescriptorかを表す定数。Device descriptorはTUSB_DESC_DEVICE=0x01 |
bcdUSB | USB仕様のリリース番号。USB2.0なら0x0200 |
bDeviceClass | USB仕様参照。0だとinterfaceごとに指定 |
bDeviceSubClass | USB仕様参照。bDeviceClassが0だとこれも0でないといけない |
bDeviceProtocol | USB仕様参照。0xFFだとベンダ依存 |
bMaxPacketSize0 | endpoint0のpacket size。HullSpeedなら64固定 |
idVendor | ベンダID |
idProduct | プロダクトID |
iManufacturer | string descriptorへのindex |
iProduct | 同上 |
iSerialNumber | 同上 |
bNumConfigurations | configuration descriptorの数 |
この構造体のメンバを埋めるヘルパ関数でもあるか、と思って探したけどほんのちょっとだけ。自分でUSBの仕様に従って埋めていくしかない。いちおうこのtusb_types.hのファイルの初めの方に読みやすく文字でdefineされた定数がenumであるので、実際にdescriptorを書くときはその定数を使うのがいい。
15.3.2 configuration descriptor
あと同様にconfiguration descriptorは/// USB Configuration Descriptor typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type uint16_t wTotalLength ; ///< Total length of data returned for this co uint8_t bNumInterfaces ; ///< Number of interfaces supported by this conf uint8_t bConfigurationValue ; ///< Value to use as an argument to the SetC uint8_t iConfiguration ; ///< Index of string descriptor describing this uint8_t bmAttributes ; ///< Configuration characteristics uint8_t bMaxPower ; ///< Maximum power consumption of the } tusb_desc_configuration_t;
Table 2: configuration descriptorの意味
bLength: | descriptorのバイト数 |
bDescriptorType | configuration descriptorはTUSB_DESC_CONFIGURATION=0x02 |
wTotalLength: | interface, endpoint descriptorまで含めたバイト数 |
bNumInterfaces: | configurationに含まれるinterface descriptorの数 |
bConfigurationValue: | このdescriptorを指定するための番号 |
iConfiguration: | string descriptorへのindex |
bmAttributes: | ビットフィールド |
bMaxPower: | 最大消費電力。2mA単位で |
bmAttributesはビットフィールドで、
7: | 1に固定 |
6: | self-poweredなら1 |
5: | remote-wakeupなら1 |
4..0: | 予約0x0 |
となっている。
device/subd.hに設定用の簡単なmacroがある。
#define TUD_CONFIG_DESCRIPTOR(config_num, _itfcount, _stridx, _total_len, _attribute, _power_ma)
2021-07-11 21:24
nice!(0)
コメント(0)
コメント 0