web-dev-qa-db-ja.com

カスタムHIDデバイスHIDレポート記述子

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
};
14
Amomum
  1. すべての公式ドキュメントはusb.orgで入手できます。 HIDレポート記述子を理解するには、 HID情報 ページのドキュメントのいくつかを読む必要があります。特に、次のことを理解する必要があります。

    • 「HID 1.11のデバイスクラス定義」ドキュメント-ヒューマンインターフェイスデバイスレポート形式について説明しています
    • 「HID Usage Tables 1.12」ドキュメント-レポート記述子に表示される可能性のある多くの使用状況ページの値とそれらのページ内の使用状況について説明しています

    そうは言っても、このドキュメントは悪名高いものであり、消化するにはかなりの労力が必要です。

  2. 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.
    
  3. ガイドとして、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;
    
  4. 各レポートにLOGICAL_MINIMUMおよびLOGICAL_MAXIMUMを指定する必要がありますか?番号。

    一部の項目はGLOBALです(つまり、レポート記述子が順次解析されるため、それらの値は別のGLOBAL項目によって明示的に変更されるまで残ります)とその他の項目はLOCALです(つまり、MAIN項目が検出されるたびに値がデフォルトにリセットされます) )。 LOGICAL_MINIMUMとLOGICAL_MAXIMUMはどちらもGLOBALアイテムであるため、値を変更する場合にのみ、値を再指定する必要があります。私の意見では、項目の公式名の前にGLOBAL_、LOCAL_、およびMAIN_を付けると、仕様はより明確になりますが、残念ながら、私たちは全員、現状の仕様に準拠する必要があります。

  5. 上記の例は、SourceForgeの無料ツール hidrdd を使用してデコードされました

19
aja

@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
}
_

注意すべき点がいくつかあります。

  • さらに多くの入力/出力ペアを簡単に追加できます。別のレポートIDを指定するだけです。各メッセージ定義は10バイトで構成されているため、簡単に追加できます。
  • 記述子のバイト数を追跡​​して、配列のサイズを計算できるようにします(#define REPORT_DESC_SIZE (55))。

Windows側では Mike O'BrienのHIDLibrary を使用します。 HIDレポートには通常、レポートIDが付加されます。HIDLibraryでは、_HidReport.ReportID_フィールドを使用して値を設定/取得します。ボード側では、レポートの最初のバイトがレポートIDになることに注意してください。

8
D. Shinobi

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 */

それがきちんと動くかどうか私は確信がない。わかります。

2
Amomum

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;

};

0
Vivek yadav

以下は、閲覧目的のための スペックシート (または「マニュアル」)へのリンクです。

いくつかの質問に答えるために、REPORT_SIZEはビットで指定され、REPORT_COUNTは、指定されたプロパティで報告される「使用法」の数を指定するために使用できます。たとえば、XYの使用法のプロパティを設定し、REPORT_COUNTを2として指定し(XとYに1つずつ)、次にINPUTを指定して、それらの使用法をレポートに追加します。次に、他の使用法について説明します。

また、使用量バイトを揃えることを忘れないでください。 REPORT_COUNTはビット単位で指定されるため、使用法のバイトを揃えることを忘れがちです。したがって、1つの使用法が1ビットのみの場合、7バイトを超える必要がある場合は、次の使用法に移る前に、そのバイトに7ビットが使用されないように指定する必要があります。

0
Chef Pharaoh