HID記述子の生成に少し問題があります。入力用にID1、出力用に64バイトのデータを持つID2の単純なレポートを使用したいと思います。
Rtfmingとgooglingを実行しても、HID記述子の一部のフィールドについてはまだ手掛かりがないことに気付きました。
誰かが私にすべての記述子フィールドの意味を見つけることができるヒントまたはマニュアルを教えてもらえますか? HID-mouse/joistick/keyboardの例だけが見つかりました。
たとえば-REPORT_SIZE-サイズはバイト単位ですか、ビット単位ですか?そして、なぜREPORT_COUNTもあるのですか?レポートに64バイトがある場合、LOGICAL_MAXIMUMは255または255 * 64である必要がありますか?
すべてのレポートにLOGICAL_MAXとMINを書き込む必要がありますか?
または、多分これは(推測によって生成された)で十分でしょうか?
char ReportDescriptor[39] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x00, // USAGE (Undefined)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x00, // USAGE (Undefined)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x40, // REPORT_SIZE (64)
0x96, 0x00, 0x02, // REPORT_COUNT (512)
0x81, 0x82, // INPUT (Data,Var,Abs,Vol)
0x85, 0x02, // REPORT_ID (2)
0x09, 0x00, // USAGE (Undefined)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x40, // REPORT_SIZE (64)
0x96, 0x00, 0x02, // REPORT_COUNT (512)
0x91, 0x82, // OUTPUT (Data,Var,Abs,Vol)
0xc0 // END_COLLECTION
};
すべての公式ドキュメントはusb.orgで入手できます。 HIDレポート記述子を理解するには、 HID情報 ページのドキュメントのいくつかを読む必要があります。特に、次のことを理解する必要があります。
そうは言っても、このドキュメントは悪名高いものであり、消化するにはかなりの労力が必要です。
REPORT_SIZEは、バイトではなくビット単位のレポートのサイズです。 REPORT_SIZEはフィールドの幅(ビット単位)として、REPORT_COUNTは(その幅の)フィールド数として考えてください。これは、次のように「HID 1.11のデバイスクラス定義」のセクション6.2.2.7「グローバルアイテム」で明らかにされています。
Global Item Tag One-byte Prefix Description
Report Size 0111 01 nn Unsigned integer specifying the size of the report
fields in bits. This allows the parser to build an
item map for the report handler to use. For more
information, see Section 8: Report Protocol.
ガイドとして、64バイトの入力バッファー(REPORT_IDが0x01のホストへの)と64バイトの出力バッファー(REPORT_IDのホストからの)を記述する妥当な(つまり、テストしていません)レポート記述子0x02)は次のようになります。
0x06, 0x00, 0xFF, // (GLOBAL) USAGE_PAGE 0xFF00 Vendor-defined
0xA1, 0x01, // (MAIN) COLLECTION 0x01 Application (Usage=0x0: Page=, Usage=, Type=) <-- Warning: USAGE type should be CA (Application)
0x15, 0x00, // (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0
0x26, 0xFF, 0x00, // (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255)
0x75, 0x08, // (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
0x85, 0x01, // (GLOBAL) REPORT_ID 0x01 (1)
0x95, 0x40, // (GLOBAL) REPORT_COUNT 0x40 (64) Number of fields
0x09, 0x01, // (LOCAL) USAGE 0xFF000001
0x81, 0x02, // (MAIN) INPUT 0x00000002 (64 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
0x85, 0x02, // (GLOBAL) REPORT_ID 0x02 (2)
0x09, 0x01, // (LOCAL) USAGE 0xFF000001
0x91, 0x02, // (MAIN) OUTPUT 0x00000002 (64 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
0xC0, // (MAIN) END_COLLECTION Application
これは、次のC言語構造体の定義に対応しています。
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 01 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x01 (1)
uint8_t VEN_VendorDefined0001[64]; // FF00 0001 Value = 0 to 255
} inputReport01_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 02 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x02 (2)
uint8_t VEN_VendorDefined0001[64]; // FF00 0001 Value = 0 to 255
} outputReport02_t;
各レポートにLOGICAL_MINIMUMおよびLOGICAL_MAXIMUMを指定する必要がありますか?番号。
一部の項目はGLOBALです(つまり、レポート記述子が順次解析されるため、それらの値は別のGLOBAL項目によって明示的に変更されるまで残ります)とその他の項目はLOCALです(つまり、MAIN項目が検出されるたびに値がデフォルトにリセットされます) )。 LOGICAL_MINIMUMとLOGICAL_MAXIMUMはどちらもGLOBALアイテムであるため、値を変更する場合にのみ、値を再指定する必要があります。私の意見では、項目の公式名の前にGLOBAL_、LOCAL_、およびMAIN_を付けると、仕様はより明確になりますが、残念ながら、私たちは全員、現状の仕様に準拠する必要があります。
上記の例は、SourceForgeの無料ツール hidrdd を使用してデコードされました
@ajaが上で述べたように、公式のUSB文書はややあいまいです。私はこのテンプレートを(主にこのページの助けを借りて)カスタムボードと通信するための簡単な出発点として作成しました。 HIDコードは、仮想COMポートプロトコルを置き換えることを目的としています。 HIDの大きな利点は、ドライバーが不要なことです。
_uint8_t CUSTOM_HID_ReportDesc[REPORT_DESC_SIZE] =
{
0x06, 0x00, 0xFF, // Global Usage page = 0xFF00 (Vendor-defined pages are in the range 0xFF00 through 0xFFFF)
0x09, 0x01, // Local Usage (vendor usage 1)
0xA1, 0x01, // Main Collection (application) begin
0x15, 0x00, // Global Logical minimum (0) applies to each byte
0x26, 0xFF, 0x00, // Global Logical maximum (255)
0x75, 0x08, // Global Report Size (8 bits)
// 14 bytes | Output message 1 (sent from Host to device)
0x85, 1, // Global Report ID (cannot be 0)
0x98, 64, // Global Report Count (number of Report Size fields, in this case 64 bytes)
0x19, 0x01, // Local Usage Minimum (each Report Count must be associated with a Usage)
0x19, 0x40, // Local Usage Maximum
0x91, 0x02, // Main Output (data, array, absolute)
// 24 bytes | Input message 1 (sent from device to Host)
0x85, 1, // Global Report ID (cannot be 0)
0x98, 64, // Global Report Count (number of Report Size fields)
0x19, 0x01, // Local Usage Minimum (each Report Count must be associated with a Usage)
0x19, 0x40, // Local Usage Maximum
0x81, 0x02, // Main Input (data, array, absolute)
// 34 bytes | Output message 2 (sent from Host to device)
0x85, 2, // Global Report ID (cannot be 0)
0x98, 12, // Global Report Count (number of Report Size fields)
0x19, 0x01, // Local Usage Minimum (each Report Count must be associated with a Usage)
0x19, 0x40, // Local Usage Maximum
0x91, 0x02, // Main Output (data, array, absolute)
// 44 bytes | Input message 2 (sent from device to Host)
0x85, 2, // Global Report ID (cannot be 0)
0x98, 57, // Global Report Count (number of Report Size fields)
0x19, 0x01, // Local Usage Minimum (each Report Count must be associated with a Usage)
0x19, 0x40, // Local Usage Maximum
0x81, 0x02, // Main Input (data, array, absolute)
// 54 bytes | End (add one byte)
0xC0 // Main Collection (application) end
}
_
注意すべき点がいくつかあります。
#define REPORT_DESC_SIZE (55)
)。Windows側では Mike O'BrienのHIDLibrary を使用します。 HIDレポートには通常、レポートIDが付加されます。HIDLibraryでは、_HidReport.ReportID
_フィールドを使用して値を設定/取得します。ボード側では、レポートの最初のバイトがレポートIDになることに注意してください。
Win7でカスタムhidデバイスが検出されました(これを推測して作成し、例から盗みました)。
{
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x00, // USAGE (Undefined)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x85, 0x01, // REPORT_ID (1)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x40, // REPORT_COUNT (64)
0x09, 0x00, // USAGE (Undefined)
0x81, 0x82, // INPUT (Data,Var,Abs,Vol) - to the Host
0x85, 0x02, // REPORT_ID (2)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x40, // REPORT_COUNT (64)
0x09, 0x00, // USAGE (Undefined)
0x91, 0x82, // OUTPUT (Data,Var,Abs,Vol) - from the Host
0xc0 // END_COLLECTION
}; /* CustomHID_ReportDescriptor */
それがきちんと動くかどうか私は確信がない。わかります。
HIDレポート記述子は、キーと値のペアです。それらを理解するには、HID仕様を読んでください。この場合、第6章が役立ちます。これらの値の由来と、記述子への影響はどこにありますか?それらを変更した場合。
Key , value
--------------
0x85, 0x02, // REPORT_ID (2)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x40, // REPORT_COUNT (64)
@Trick:REPORT_COUNT(0x95)AND REPORT_SIZE(0x75)を理解するために問題に直面している場合は、2D配列として想像できます。
Array[count][size] = Array[4][8] /* value are in [Bytes][bit] */
Where 4 represent total number of reports to be send and 8 shows size of each report.
つまり、構造体レポート{
uint8_t report_1;
uint8_t report_2;
uint8_t report_3;
uint8_t report_4;
};
以下は、閲覧目的のための スペックシート (または「マニュアル」)へのリンクです。
いくつかの質問に答えるために、REPORT_SIZE
はビットで指定され、REPORT_COUNT
は、指定されたプロパティで報告される「使用法」の数を指定するために使用できます。たとえば、X
とY
の使用法のプロパティを設定し、REPORT_COUNT
を2として指定し(XとYに1つずつ)、次にINPUT
を指定して、それらの使用法をレポートに追加します。次に、他の使用法について説明します。
また、使用量バイトを揃えることを忘れないでください。 REPORT_COUNT
はビット単位で指定されるため、使用法のバイトを揃えることを忘れがちです。したがって、1つの使用法が1ビットのみの場合、7バイトを超える必要がある場合は、次の使用法に移る前に、そのバイトに7ビットが使用されないように指定する必要があります。