次の方法で共有


入力デバイス触覚実装ガイド

このドキュメントでは、互換性のある Windows 11 ホストに接続する触覚対応入力デバイスのプロトコル実装について詳しく説明します。 これには、入力デバイスのハードウェア内で触覚応答を生成するための機械的制約、電気的制約、コンポーネント選択に関するガイダンスは含まれません。

サポートされるデバイス クラス

Windows 11 では、触覚対応入力デバイスの次のクラスがサポートされています。

  • 触覚タッチパッドは、Windows 上のタッチパッド デバイス クラスの拡張機能です。 この実装ガイドは タッチパッド実装ガイド に追加され、タッチパッド デジタイザー内での触覚の実装に重点を置いているため、触覚タッチパッドは、ここに含まれている要件に加えて 、タッチパッド実装ガイド の要件を満たす必要があります。

  • 触覚マウスは、Windows 上のマウス デバイス クラスの拡張機能です。 触覚マウスは、このドキュメントに含まれる要件を満たす必要があります。

注: 触覚対応ペン入力デバイスは、このドキュメントでは説明しない特殊なデバイス クラスです。 触覚フィードバックを使用してペン デバイスを実装する方法については、「 触覚ペン実装ガイド」を参照してください。

入力デバイス触覚プロトコルの実装

ここに示されている情報を理解するには、HID プロトコルを十分に理解する必要があります。 HID プロトコルの詳細については、次のリソースを参照してください。

触覚対応入力デバイスファームウェアは、このトピックで説明されている使用状況のみを報告する必要があります。 Windows では、ファームウェアと独自の HID ドライバーを使用してデバイスを有効にし、Windows アプリケーションにデバイスへのアクセス権を付与します。

サポートされている各デバイス クラスのサンプル記述子については、後述の「サンプル レポート記述子」セクションを参照してください。

一般的なガイダンス

このセクションの項目は、入力触覚デバイスのすべてのクラスに適用されます。

必要な HID コレクション

触覚に関連する機能は、HID SimpleHapticsController コレクション (Page 0xE、Usage 0x1) に含める必要があります。

触覚タッチパッド デバイスの場合、このコレクションは Windows Precision タッチパッドの最上位コレクションの子である必要があります。

触覚マウス デバイスの場合、このコレクションは最上位レベルのコレクションであり、マウスの最上位のコレクションの兄弟である必要があります。

触覚フィードバックの Device-Initiated

触覚対応入力デバイスは、必要に応じて、押されたボタンや離されたボタンへの応答など、独自の触覚フィードバックの開始をサポートできます。

触覚タッチパッドの場合、以下の「触覚タッチパッドガイダンス」セクションでは、触覚フィードバックを開始するときにユーザーが動作をカスタマイズできるように、デバイスがSET_FEATUREレポートをサポートすることを選択する方法について説明します。

触覚マウスはデバイスによって開始されるフィードバックをトリガーできますが、Windows にはこの動作を構成するメカニズムはありません。

触覚フィードバックの Host-Initiated

触覚対応入力デバイスは、ホストによって開始される触覚フィードバックをサポートできます。これは列挙後いつでも発生します。

触覚タッチパッドとマウスは、必要に応じてホストによって開始されるフィードバックをサポートできます。 触覚タッチパッドの場合、ホストによって開始されるフィードバックがサポートされている場合は、デバイスによって開始されるフィードバックのカスタマイズに関するSET_FEATUREレポートの両方もサポートされている必要があります。

ホストによって開始される触覚フィードバックのサポートには、2 つの SimpleHapticsController 論理子コレクション (Page 0x0E、Usage 0x01) が必要です。 これらの論理コレクションは、実装するデバイス クラスのメイン SimpleHapticsController コレクションの子である必要があり (前述の「Required HID Collection」セクションに記載されています)、タッチパッドのデバイスによって開始される触覚フィードバックの強度を構成するために使用されるコレクションとは別にする必要があります。 これらの論理子コレクションの 1 つは、サポートされている波形とその期間を照会するためにホストによって使用されるGET_FEATURE レポートを定義する必要があります。 もう 1 つの論理子コレクションでは、ハプティックを手動でトリガーするためにホストによって使用される出力レポートを定義する必要があります。

デバイスは、自動トリガーされた触覚のサポートを宣言しないでください。また、デバイスは連続波形をサポートしてはなりません。

波形

次の表では、触覚対応入力デバイスのホストでサポートされる波形を定義します。 デバイスでサポートされる波形は序数に関連付けられます。 波形の使用状況と継続時間は、波形情報機能レポート (下記参照) を介してホストに提供されます。 フィードバックをトリガーするときに、ホストは、手動トリガーの使用の値として目的の波形の序数を提供します。

必須と省略可能
波形 Description ページ ID 必須/省略可能
None No-op。 進行中の波形の再生状態に影響を与えてはならない 0x0E 0x1001 Mandatory
止まれ 進行中の波形の再生を停止します 0x0E 0x1002 Mandatory
Hover ホバーを示し、今後のアクションの可能性を通知するために使用される光パルス 0x0E 0x1008 Mandatory
衝突する 画面の境界またはスライダーとスクロール バーの端との衝突を示すために使用されるソフト パルス 0x0E 0x1012 Mandatory
並べる ガイドまたはキャンバスエッジとのドラッグ、スケール、または回転操作中にオブジェクトの配置を確認する鮮明なパルス 0x0E 0x1013 Mandatory
Step スライダー、リスト、またはスクラバーの項目をステップ実行するために使用される強固なパルス 0x0E 0x1014 Mandatory
Grow モーション、遷移、またはインテリジェント なシステム アクティビティを伝達する動的パルス 0x0E 0x1015 Mandatory
押す サーフェス ボタンが押されたと判断したときにデバイスによってトリガーされる触覚信号。 サポートされている場合は、リリースもサポートされている必要があります。 0x0E 0x1006 オプション
リリース サーフェス ボタンが離されたと判断したときにデバイスによってトリガーされる触覚信号。 サポートされている場合は、Press もサポートされている必要があります。 0x0E 0x1007 オプション
Success アクションが成功したことをユーザーに警告する強力な触覚信号 0x0E 0x1009 オプション
エラー アクションが失敗したか、エラーが発生したことをユーザーに通知するための強力な触覚信号 0x0E 0x100A オプション
許可されていません

以下の波形はサポートできません。

波形 ID 注記
Click 0x1003 ボタンを押すと、既存の触覚フィードバックと混同する可能性があります。
連続バズ 0x1004 連続波形はサポートされません。
連続ランブル 0x1005 連続波形はサポートされません。
インク連続 0x100B ペンにのみ適用されます。
鉛筆連続 0x100C ペンにのみ適用されます。
連続マーカー 0x100D ペンにのみ適用されます。
チゼルマーカー連続 0x100E ペンにのみ適用されます。
連続ブラシ 0x100F ペンにのみ適用されます。
消しゴム連続 0x1010 ペンにのみ適用されます。
連続輝き 0x1011 ペンにのみ適用されます。

波形情報機能レポート

ホストは、サポートされている波形をデバイスに照会するときに、このGET_FEATURE レポートを発行します。 この機能レポートには、専用のレポート ID が必要です。

論理コレクションには、波形リスト用と期間リスト用の 2 つの子論理コレクションが必要です。 これらのコレクションでは、序数ページ (0x0A) で使用範囲を定義する必要があります。これにより、ホストは各序数に関連付けられている波形と期間を照会できます。

必須と省略可能な使用法
メンバー Description ページ ID 必須/省略可能
波形リスト デバイスでサポートされている触覚波形の順序付きリストを含む論理コレクション 0x0E 0x10 Mandatory
期間リスト 波形リスト内の波形の継続時間の順序付きリストを含む論理コレクション 0x0E 0x11 Mandatory
波形リスト (必須)

このコレクションは、序数と対応する波形間のマッピングを提供します。 序数 1 と 2 はWAVEFORM_NONEに対応し、暗黙的にWAVEFORM_STOPし、記述子で宣言する必要はありません。 したがって、コレクションの使用範囲の使用量の最小値は 3 にすることができ、使用量の最大値は、サポートされているすべての波形に序数を割り当てるのに十分な大きさにする必要があります。

使用量の最大値がデバイスでサポートされている波形の数よりも大きい場合、デバイスはサポートされていない序数のWAVEFORM_NONEを報告する必要があります。

使用範囲の論理範囲には、サポートされているすべての波形使用法が含まれている必要があります。 物理範囲と単位は 0 である必要があります。

期間リスト (必須)

このコレクションは波形リストで定義される波形の期間を提供する。 コレクションの使用範囲の使用量の最小値と最大値は、波形リストと同じである必要があります。

離散波形には、0 以外の継続時間が必要です。 WAVEFORM_NONEとWAVEFORM_STOPが指定されている場合は、期間が 0 である必要があります。

使用範囲の論理最小値は 0 でなければならず、論理最大値は最長の離散波形の継続時間と同じ大きさにする必要があります。 ホストは論理値をミリ秒として扱います。 物理範囲は、0 であるか、論理範囲と同じである必要があります。 物理範囲と論理範囲が一致する場合、単位はミリ秒にする必要があります。

手動トリガー出力レポート

ホストは、個別の触覚フィードバックをトリガーするときにこのレポートを発行します。 この出力レポートには、専用のレポート ID が必要です。

必須と省略可能な使用法
メンバー Description ページ ID 必須/省略可能
手動トリガー ホストから明示的なコマンドとして起動する波形 0x0E 0x21 Mandatory
強度 フィードバックの強度 0x0E 0x23 Mandatory
繰り返し回数 最初の再生後にフィードバックを繰り返す回数 0x0E 0x24 オプション
リトリガー期間 繰り返しの際にフィードバックを再トリガーするまでの待機時間 0x0E 0x25 オプション
波形カットオフ時間 フィードバックが途切れる前に再生できる最大時間 0x0E 0x28 オプション
禁止されている使用法
Usage ID 注記
自動トリガー 0x20 ホストではサポートされていません。
関連付けられたコントロールの自動トリガー 0x22 ホストではサポートされていません。
手動トリガー (必須)

この使用法には、ホストによって再生が要求された波形情報機能レポートから定義された波形の序数が含まれます。 WAVEFORM_NONE以外の序数を含む出力レポートがデバイスに送信されると、出力レポートに含まれる追加のプロパティ (サポートされている場合は、強度、繰り返しカウント、リトリガー期間、カットオフ時間) を使用して、指定された波形の再生をすぐに開始する必要があります。 デバイスでは、個別の波形、WAVEFORM_NONE、およびWAVEFORM_STOPの序数のみを使用する必要があります。 序数がWAVEFORM_STOPに対応する場合は、継続的な個別波形再生を停止する必要があります。 序数がWAVEFORM_NONEに対応する場合は、アクションを実行せず、継続的な触覚フィードバックを引き続き再生する必要があります。

論理範囲には、暗黙的な序数 1 (WAVEFORM_NONE) と 2 (WAVEFORM_STOP) を含む、可能なすべての序数を含める必要があります。 物理範囲と単位は 0 である必要があります。

強度 (必須)

この使用法は、要求された波形に適用する最大強度の割合を表し、論理最大値は最大強度を表し、論理最小値はフィードバックをまったく表しません。

論理最小値は 0 で、デバイスの機能に基づいて論理最大値を選択する必要があります。たとえば、デバイスが 4 レベルの強度をサポートしている場合、論理最大値は 4 である必要があります。 デバイスがより細かい強度をサポートしている場合、論理最大値は大きくなる可能性がありますが、100 を超えないようにしてください。 デバイスは少なくとも 4 つのレベルの強度をサポートする必要があるため、最小論理最大値は 4 です。 強度が 0 の場合は、フィードバックを再生する必要がないことを示します。ホストはこの値をWAVEFORM_STOPにのみ使用します。

物理範囲と単位は 0 である必要があります。

Repeat Count (省略可能)

この使用法は、最初の再生後に波形を繰り返す回数を表します。 0 の値は、波形を 1 回だけ再生する必要があることを示します。

この使用がサポートされている場合は、リトリガー期間とカットオフ時間の使用もサポートされている必要があります。

論理最小値は 0、論理最大値は 0 より大きい必要があります。 論理最大値は、小さい値 (たとえば、10) に制限する必要があります。 物理範囲と単位は 0 である必要があります。

リトリガー期間 (省略可能)

この使用法は、前のトリガーの開始時刻から測定された、波形のリトリガー間の継続時間を表します。 値 0 は、波形の既定の継続時間と同じとして解釈する必要があるため、リトリガーは前の値が完了した直後に行われます。 波形の既定の継続時間より小さい値は、波形を中断して再起動する必要があります。

この使用がサポートされている場合は、繰り返し回数とカットオフ時間の使用量もサポートされている必要があります。

ホストは論理値をミリ秒として扱います。 論理最小値は 0 で、論理最大値は少なくとも 1000 (1 秒を表す) である必要があります。 物理範囲は、0 であるか、論理範囲と同じである必要があります。 物理範囲が 0 以外の場合、単位はミリ秒にする必要があります。

波形カットオフ時間 (オプション)

この使用は、繰り返し回数とリトリガー期間を考慮して、1 つのトリガーが再生に至る最大時間を表します。

この使用がサポートされている場合は、繰り返しカウントとリトリガーの使用もサポートされている必要があります。

ホストは論理値をミリ秒として扱います。 最小の論理値は、最も長い離散波形の継続時間と同じ大きさで、繰り返しカウント使用量の論理最大値を乗算する必要があります。 物理範囲は、0 であるか、論理範囲と同じである必要があります。 物理範囲が 0 以外の場合、単位はミリ秒にする必要があります。

触覚タッチパッドのガイダンス

このセクションの項目は、触覚タッチパッドにのみ適用されます。

触覚フィードバックの Device-Initiated

触覚タッチパッドは、タッチパッドのサーフェス ボタンが押されたか離されたと判断したときに触覚フィードバックをトリガーする役割を担います。 SET_FEATURE レポートをサポートして、ユーザーがその動作をカスタマイズできるようにすることができます。

  • 触覚フィードバックの強度
  • ボタン押下をトリガーするために必要な強制

タッチパッドがホストによって開始される触覚フィードバックもサポートしている場合、これらの機能レポートはどちらも必須です。 各レポートには個別のレポート ID を使用する必要があります。他の使用状況では使用されません。

列挙中、ホストは記述子からサポートされている論理範囲と物理範囲を評価し、既定を含む設定 UI の公開オプションを計算します。 ホストは、ユーザーが指定した値をデバイスに通信するためにSET_FEATUREを発行しなければなりません。この発行はいつでも発生する可能性がありますが、設定が変更されるたびに、ユーザースイッチが発生し、デバイスが列挙またはリセットされたときに発生します。

触覚強度特徴レポート

このSET_FEATURE レポートでは、ボタンの押下と離しに対する触覚フィードバックの強度に対するユーザーの好みを指定します。 デバイスでサポートされている場合、ホストによって開始されるフィードバックの強度には適用されません。 この構成をサポートするには、デバイスは、専用のレポート ID を持つ機能レポートとして触覚強度の使用状況 (ページ0x0E、使用状況0x23) を含む、Windows Precision タッチパッドの最上位レベルのコレクションで SimpleHapticsController 論理子コレクション (ページ 0x0E、使用状況0x01) を定義する必要があります。 この子コレクションには、自動トリガー (ページ 0x0E、使用状況0x20) または手動トリガー (ページ 0x0E、使用状況0x21) の使用法を含めてはなりません。

論理最小値は 0 に等しい必要があります。 ユーザーの設定は論理的な範囲に線形的にスケーリングされ、ゼロはボタンの押下と離しに対してフィードバックをトリガーする必要がないことを示します。

ボタン押下しきい値機能レポート

このSET_FEATURE レポートでは、ボタンの押下をトリガーするために必要な力の量に対するユーザーの好みを指定します。 この構成をサポートするには、デバイスで、Windows Precision タッチパッドの最上位コレクションの専用レポート ID を持つ機能レポートとして、ボタン押下しきい値の使用状況 (ページ 0x0D、使用状況0xB0) を定義する必要があります。

論理範囲は、物理的な値の範囲に線形的にマップされ、均等に間隔を取り、既定値の中心に配置されます。 論理範囲を取得すると、既定値は次の式を使用して計算されます。

既定のボタン押下しきい値を論理単位で計算するための数式を示す図

論理最小値、既定、および論理最大値は、Windows 設定 UI (それぞれ "Low"、"Medium"、"High" をサポート) を介してユーザーに公開される 3 つの異なるレベルのボタン押下力に対応します。

ボタン押下しきい値の推奨される物理的範囲は、少なくとも 110g から 190g の範囲をカバーし、それぞれ最小値と最大値に対応することです。 物理最大値 190g、物理最小値 110g を使用するサンプル記述子 (上の数式に基づく既定値は 150g) については、「 サンプル レポート記述子」を参照してください。

HID レポート記述子のサンプル

触覚タッチパッド記述子のサンプル

次の記述子は、すべての必須およびオプションの使用法をサポートしています。 5つの波形のサポートを宣言し、最長で50msの期間を持つ。

すべての論理範囲は、デバイスのサポートに基づいて更新する必要があります。 異なる数の波形をサポートするには:

  • 手動トリガーの使用の論理範囲を更新する必要がある
  • 波形リストと期間リストの使用範囲とレポート数を更新する必要があります

異なる最大波形長をサポートするには、次の論理範囲を更新する必要があります。

  • リトリガー期間 (出力)
  • 波形カットオフ時間(出力)
  • 期間リスト (機能)
0x05, 0x0D,       // UsagePage(Digitizers[0x000D])
0x09, 0x05,       // UsageId(Touch Pad[0x0005])
0xA1, 0x01,       // Collection(Application)
0x85, 0x40,       //  ReportId(64)
0x05, 0x0D,       //  UsagePage(Digitizers[0x000D])
0x09, 0xB0,       //  UsageId(Button Press Threshold[0x00B0])
0x35, 0x6E,       //  PhysicalMinimum(110)
0x46, 0xBE, 0x00, //  PhysicalMaximum(190)
0x66, 0x01, 0x01, //  Unit('gram', SiLinear, Gram:1)
0x55, 0x00,       //  UnitExponent(1)
0x15, 0x01,       //  LogicalMinimum(1)
0x25, 0x03,       //  LogicalMaximum(3)
0x95, 0x01,       //  ReportCount(1)
0x75, 0x08,       //  ReportSize(8)
0xB1, 0x02,       //  Feature(Data, Variable, Absolute)
0x85, 0x41,       //  ReportId(65)
0x05, 0x0E,       //  UsagePage(Haptics[0x000E])
0x09, 0x01,       //  UsageId(Simple Haptic Controller[0x0001])
0xA1, 0x02,       //  Collection(Logical)
0x05, 0x0E,       //   UsagePage(Haptics[0x000E])
0x09, 0x23,       //   UsageId(Intensity[0x0023])
0x35, 0x00,       //   PhysicalMinimum(0)
0x45, 0x00,       //   PhysicalMaximum(0)
0x65, 0x00,       //   Unit(None)
0x55, 0x00,       //   UnitExponent(1)
0x15, 0x00,       //   LogicalMinimum(0)
0x25, 0x04,       //   LogicalMaximum(4)
0x95, 0x01,       //   ReportCount(1)
0x75, 0x08,       //   ReportSize(8)
0xB1, 0x02,       //   Feature(Data, Variable, Absolute)
0xC0,             //  EndCollection()
0x85, 0x42,       //  ReportId(66)
0x05, 0x0E,       //  UsagePage(Haptics[0x000E])
0x09, 0x01,       //  UsageId(Simple Haptic Controller[0x0001])
0xA1, 0x02,       //  Collection(Logical)
0x05, 0x0E,       //   UsagePage(Haptics[0x000E])
0x09, 0x10,       //   UsageId(Waveform List[0x0010])
0xA1, 0x02,       //   Collection(Logical)
0x05, 0x0A,       //    UsagePage(Ordinal[0x000A])
0x19, 0x03,       //    UsageIdMin(Instance 3[0x0003])
0x29, 0x07,       //    UsageIdMax(Instance 7[0x0007])
0x35, 0x00,       //    PhysicalMinimum(0)
0x45, 0x00,       //    PhysicalMaximum(0)
0x65, 0x00,       //    Unit(None)
0x55, 0x00,       //    UnitExponent(1)
0x16, 0x03, 0x10, //    LogicalMinimum(4,099)
0x26, 0xFF, 0x2F, //    LogicalMaximum(12,287)
0x95, 0x05,       //    ReportCount(5)
0x75, 0x10,       //    ReportSize(16)
0xB1, 0x02,       //    Feature(Data, Variable, Absolute)
0xC0,             //   EndCollection()
0x05, 0x0E,       //   UsagePage(Haptics[0x000E])
0x09, 0x11,       //   UsageId(Duration List[0x0011])
0xA1, 0x02,       //   Collection(Logical)
0x05, 0x0A,       //    UsagePage(Ordinal[0x000A])
0x19, 0x03,       //    UsageIdMin(Instance 3[0x0003])
0x29, 0x07,       //    UsageIdMax(Instance 7[0x0007])
0x35, 0x00,       //    PhysicalMinimum(0)
0x45, 0x32,       //    PhysicalMaximum(50)
0x66, 0x01, 0x10, //    Unit('millisecond', SiLinear, Seconds:1)
0x55, 0x0D,       //    UnitExponent(0.001)
0x15, 0x00,       //    LogicalMinimum(0)
0x25, 0x32,       //    LogicalMaximum(50)
0x95, 0x05,       //    ReportCount(5)
0x75, 0x08,       //    ReportSize(8)
0xB1, 0x02,       //    Feature(Data, Variable, Absolute)
0xC0,             //   EndCollection()
0xC0,             //  EndCollection()
0x85, 0x43,       //  ReportId(67)
0x05, 0x0E,       //  UsagePage(Haptics[0x000E])
0x09, 0x01,       //  UsageId(Simple Haptic Controller[0x0001])
0xA1, 0x02,       //  Collection(Logical)
0x05, 0x0E,       //   UsagePage(Haptics[0x000E])
0x09, 0x21,       //   UsageId(Manual Trigger[0x0021])
0x35, 0x00,       //   PhysicalMinimum(0)
0x45, 0x00,       //   PhysicalMaximum(0)
0x65, 0x00,       //   Unit(None)
0x55, 0x00,       //   UnitExponent(1)
0x15, 0x01,       //   LogicalMinimum(1)
0x25, 0x07,       //   LogicalMaximum(7)
0x95, 0x01,       //   ReportCount(1)
0x75, 0x08,       //   ReportSize(8)
0x91, 0x02,       //   Output(Data, Variable, Absolute)
0x05, 0x0E,       //   UsagePage(Haptics[0x000E])
0x09, 0x23,       //   UsageId(Intensity[0x0023])
0x35, 0x00,       //   PhysicalMinimum(0)
0x45, 0x00,       //   PhysicalMaximum(0)
0x65, 0x00,       //   Unit(None)
0x55, 0x00,       //   UnitExponent(1)
0x15, 0x00,       //   LogicalMinimum(0)
0x25, 0x04,       //   LogicalMaximum(4)
0x95, 0x01,       //   ReportCount(1)
0x75, 0x08,       //   ReportSize(8)
0x91, 0x02,       //   Output(Data, Variable, Absolute)
0x05, 0x0E,       //   UsagePage(Haptics[0x000E])
0x09, 0x24,       //   UsageId(Repeat Count[0x0024])
0x35, 0x00,       //   PhysicalMinimum(0)
0x45, 0x00,       //   PhysicalMaximum(0)
0x65, 0x00,       //   Unit(None)
0x55, 0x00,       //   UnitExponent(1)
0x15, 0x00,       //   LogicalMinimum(0)
0x25, 0x05,       //   LogicalMaximum(5)
0x95, 0x01,       //   ReportCount(1)
0x75, 0x08,       //   ReportSize(8)
0x91, 0x02,       //   Output(Data, Variable, Absolute)
0x05, 0x0E,       //   UsagePage(Haptics[0x000E])
0x09, 0x25,       //   UsageId(Retrigger Period[0x0025])
0x35, 0x00,       //   PhysicalMinimum(0)
0x46, 0xE8, 0x03, //   PhysicalMaximum(1,000)
0x66, 0x01, 0x10, //   Unit('millisecond', SiLinear, Seconds:1)
0x55, 0x0D,       //   UnitExponent(0.001)
0x15, 0x00,       //   LogicalMinimum(0)
0x26, 0xE8, 0x03, //   LogicalMaximum(1,000)
0x95, 0x01,       //   ReportCount(1)
0x75, 0x10,       //   ReportSize(16)
0x91, 0x02,       //   Output(Data, Variable, Absolute)
0x05, 0x0E,       //   UsagePage(Haptics[0x000E])
0x09, 0x28,       //   UsageId(Waveform Cutoff Time[0x0028])
0x36, 0xE8, 0x03, //   PhysicalMinimum(1,000)
0x46, 0x88, 0x13, //   PhysicalMaximum(5,000)
0x66, 0x01, 0x10, //   Unit('millisecond', SiLinear, Seconds:1)
0x55, 0x0D,       //   UnitExponent(0.001)
0x16, 0xE8, 0x03, //   LogicalMinimum(1,000)
0x26, 0x88, 0x13, //   LogicalMaximum(5,000)
0x95, 0x01,       //   ReportCount(1)
0x75, 0x10,       //   ReportSize(16)
0x91, 0x02,       //   Output(Data, Variable, Absolute)
0xC0,             //  EndCollection()
0xC0,             // EndCollection()

上記の記述子は、次の Waratah ファイルを使用して生成されました。

[[settings]]
packingInBytes = 1
optimize = false

[[unit]]
name = 'millisecond'
second = [0.001, 1.0]

[[applicationCollection]]
usage = ['Digitizers', 'Touch Pad']

 # Button press threshold feature report
 [[applicationCollection.featureReport]]
 id = 0x40

  [[applicationCollection.featureReport.variableItem]]
  usage = ['Digitizers', 'Button Press Threshold']
  logicalValueRange = [1, 3]
  physicalValueRange = [110, 190]
  unit = 'gram'

 # Feedback intensity feature report
 [[applicationCollection.featureReport]]
 id = 0x41

  [[applicationCollection.featureReport.logicalCollection]]
  usage = ['Haptics', 'Simple Haptic Controller']

   [[applicationCollection.featureReport.logicalCollection.variableItem]]
   usage = ['Haptics', 'Intensity']
   logicalValueRange = [0, 4]

 # Host-initiated waveform information feature report
 [[applicationCollection.featureReport]]
 id = 0x42

  [[applicationCollection.featureReport.logicalCollection]]
  usage = ['Haptics', 'Simple Haptic Controller']

   [[applicationCollection.featureReport.logicalCollection.logicalCollection]]
   usage = ['Haptics', 'Waveform List']

    [[applicationCollection.featureReport.logicalCollection.logicalCollection.variableItem]]
    usageRange = ['Ordinal', 'Instance 3', 'Instance 7']
    logicalValueRange = [0x1003, 0x2FFF]

   [[applicationCollection.featureReport.logicalCollection.logicalCollection]]
   usage = ['Haptics', 'Duration List']

    [[applicationCollection.featureReport.logicalCollection.logicalCollection.variableItem]]
    usageRange = ['Ordinal', 'Instance 3', 'Instance 7']
    logicalValueRange = [0, 50]
    physicalValueRange = [0, 50]
    unit = 'millisecond'

 # Host-initiated waveform manual trigger output report
 [[applicationCollection.outputReport]]
 id = 0x43

  [[applicationCollection.outputReport.logicalCollection]]
  usage = ['Haptics', 'Simple Haptic Controller']

   [[applicationCollection.outputReport.logicalCollection.variableItem]]
   usage = ['Haptics', 'Manual Trigger']
   logicalValueRange = [1, 7]

   [[applicationCollection.outputReport.logicalCollection.variableItem]]
   usage = ['Haptics', 'Intensity']
   logicalValueRange = [0, 4]

   [[applicationCollection.outputReport.logicalCollection.variableItem]]
   usage = ['Haptics', 'Repeat Count']
   logicalValueRange = [0, 5]

   [[applicationCollection.outputReport.logicalCollection.variableItem]]
   usage = ['Haptics', 'Retrigger Period']
   logicalValueRange = [0, 1000]
   physicalValueRange = [0, 1000]
   unit = 'millisecond'

   [[applicationCollection.outputReport.logicalCollection.variableItem]]
   usage = ['Haptics', 'Waveform Cutoff Time']
   logicalValueRange = [1000, 5000]
   physicalValueRange = [1000, 5000]
   unit = 'millisecond'

触覚マウス記述子のサンプル

次の記述子は、すべての必須およびオプションの使用法をサポートしています。 8つの波形のサポートを宣言し、最長で200msの期間を持つ。

すべての論理範囲は、デバイスのサポートに基づいて更新する必要があります。 異なる数の波形をサポートするには:

  • 手動トリガーの使用の論理範囲を更新する必要がある
  • 波形リストと期間リストの使用範囲とレポート数を更新する必要があります

異なる最大波形長をサポートするには、次の論理範囲を更新する必要があります。

  • リトリガー期間 (出力)
  • 波形カットオフ時間(出力)
  • 期間リスト (機能)
0x05, 0x01,       // UsagePage(Generic Desktop[0x0001])
0x09, 0x02,       // UsageId(Mouse[0x0002])
0xA1, 0x01,       // Collection(Application)
0x85, 0x01,       //  ReportId(1)
0x09, 0x01,       //  UsageId(Pointer[0x0001])
0xA1, 0x00,       //  Collection(Physical)
0x09, 0x30,       //   UsageId(X[0x0030])
0x09, 0x31,       //   UsageId(Y[0x0031])
0x15, 0x80,       //   LogicalMinimum(-128)
0x25, 0x7F,       //   LogicalMaximum(127)
0x95, 0x02,       //   ReportCount(2)
0x75, 0x08,       //   ReportSize(8)
0x81, 0x06,       //   Input(Data, Variable, Relative)
0x05, 0x09,       //   UsagePage(Button[0x0009])
0x19, 0x01,       //   UsageIdMin(Button 1[0x0001])
0x29, 0x03,       //   UsageIdMax(Button 3[0x0003])
0x15, 0x00,       //   LogicalMinimum(0)
0x25, 0x01,       //   LogicalMaximum(1)
0x95, 0x03,       //   ReportCount(3)
0x75, 0x01,       //   ReportSize(1)
0x81, 0x02,       //   Input(Data, Variable, Absolute)
0xC0,             //  EndCollection()
0x95, 0x01,       //  ReportCount(1)
0x75, 0x05,       //  ReportSize(5)
0x81, 0x03,       //  Input(Constant, Variable, Absolute)
0xC0,             // EndCollection()
0x05, 0x0E,       // UsagePage(Haptics[0x000E])
0x09, 0x01,       // UsageId(Simple Haptic Controller[0x0001])
0xA1, 0x01,       // Collection(Application)
0x85, 0x10,       //  ReportId(16)
0x09, 0x10,       //  UsageId(Waveform List[0x0010])
0xA1, 0x02,       //  Collection(Logical)
0x05, 0x0A,       //   UsagePage(Ordinal[0x000A])
0x19, 0x03,       //   UsageIdMin(Instance 3[0x0003])
0x29, 0x0A,       //   UsageIdMax(Instance 10[0x000A])
0x16, 0x03, 0x10, //   LogicalMinimum(4,099)
0x26, 0xFF, 0x2F, //   LogicalMaximum(12,287)
0x95, 0x08,       //   ReportCount(8)
0x75, 0x0E,       //   ReportSize(14)
0xB1, 0x02,       //   Feature(Data, Variable, Absolute)
0xC0,             //  EndCollection()
0x05, 0x0E,       //  UsagePage(Haptics[0x000E])
0x09, 0x11,       //  UsageId(Duration List[0x0011])
0xA1, 0x02,       //  Collection(Logical)
0x05, 0x0A,       //   UsagePage(Ordinal[0x000A])
0x19, 0x03,       //   UsageIdMin(Instance 3[0x0003])
0x29, 0x0A,       //   UsageIdMax(Instance 10[0x000A])
0x46, 0xC8, 0x00, //   PhysicalMaximum(200)
0x66, 0x01, 0x10, //   Unit('millisecond', SiLinear, Seconds:1)
0x55, 0x0D,       //   UnitExponent(0.001)
0x15, 0x00,       //   LogicalMinimum(0)
0x26, 0xC8, 0x00, //   LogicalMaximum(200)
0x75, 0x08,       //   ReportSize(8)
0xB1, 0x02,       //   Feature(Data, Variable, Absolute)
0xC0,             //  EndCollection()
0x85, 0x11,       //  ReportId(17)
0x05, 0x0E,       //  UsagePage(Haptics[0x000E])
0x09, 0x21,       //  UsageId(Manual Trigger[0x0021])
0x45, 0x00,       //  PhysicalMaximum(0)
0x65, 0x00,       //  Unit(None)
0x55, 0x00,       //  UnitExponent(1)
0x15, 0x01,       //  LogicalMinimum(1)
0x25, 0x0A,       //  LogicalMaximum(10)
0x95, 0x01,       //  ReportCount(1)
0x75, 0x04,       //  ReportSize(4)
0x91, 0x02,       //  Output(Data, Variable, Absolute)
0x09, 0x23,       //  UsageId(Intensity[0x0023])
0x15, 0x00,       //  LogicalMinimum(0)
0x25, 0x04,       //  LogicalMaximum(4)
0x75, 0x03,       //  ReportSize(3)
0x91, 0x02,       //  Output(Data, Variable, Absolute)
0x09, 0x24,       //  UsageId(Repeat Count[0x0024])
0x25, 0x05,       //  LogicalMaximum(5)
0x91, 0x02,       //  Output(Data, Variable, Absolute)
0x09, 0x25,       //  UsageId(Retrigger Period[0x0025])
0x46, 0xE8, 0x03, //  PhysicalMaximum(1,000)
0x66, 0x01, 0x10, //  Unit('millisecond', SiLinear, Seconds:1)
0x55, 0x0D,       //  UnitExponent(0.001)
0x26, 0xE8, 0x03, //  LogicalMaximum(1,000)
0x75, 0x0A,       //  ReportSize(10)
0x91, 0x02,       //  Output(Data, Variable, Absolute)
0x09, 0x28,       //  UsageId(Waveform Cutoff Time[0x0028])
0x36, 0xE8, 0x03, //  PhysicalMinimum(1,000)
0x46, 0x88, 0x13, //  PhysicalMaximum(5,000)
0x16, 0xE8, 0x03, //  LogicalMinimum(1,000)
0x26, 0x88, 0x13, //  LogicalMaximum(5,000)
0x75, 0x0D,       //  ReportSize(13)
0x91, 0x02,       //  Output(Data, Variable, Absolute)
0x75, 0x07,       //  ReportSize(7)
0x91, 0x03,       //  Output(Constant, Variable, Absolute)
0xC0,             // EndCollection()

上記の記述子は、次の Waratah ファイルを使用して生成されました。

[[unit]]
name = 'millisecond'
second = [0.001, 1.0]

[[applicationCollection]]
usage = ['Generic Desktop', 'Mouse']

 # Mouse
 [[applicationCollection.inputReport]]

  [[applicationCollection.inputReport.physicalCollection]]
  usage = ['Generic Desktop', 'Pointer']

   [[applicationCollection.inputReport.physicalCollection.variableItem]]
   usage = ['Generic Desktop', 'X']
   sizeInBits = 8
   logicalValueRange = 'maxSignedSizeRange'
   reportFlags = ['relative']

   [[applicationCollection.inputReport.physicalCollection.variableItem]]
   usage = ['Generic Desktop', 'Y']
   sizeInBits = 8
   logicalValueRange = 'maxSignedSizeRange'
   reportFlags = ['relative']

   [[applicationCollection.inputReport.physicalCollection.variableItem]]
   usageRange = ['Button', 'Button 1', 'Button 3']
   logicalValueRange = [0, 1]

[[applicationCollection]]
usage = ['Haptics', 'Simple Haptic Controller']

 # Host-initiated waveform information feature report
 [[applicationCollection.featureReport]]
 id = 0x10

  [[applicationCollection.featureReport.logicalCollection]]
  usage = ['Haptics', 'Waveform List']

   [[applicationCollection.featureReport.logicalCollection.variableItem]]
   usageRange = ['Ordinal', 'Instance 3', 'Instance 10']
   logicalValueRange = [0x1003, 0x2FFF]

  [[applicationCollection.featureReport.logicalCollection]]
  usage = ['Haptics', 'Duration List']

   [[applicationCollection.featureReport.logicalCollection.variableItem]]
   usageRange = ['Ordinal', 'Instance 3', 'Instance 10']
   logicalValueRange = [0, 200]
   physicalValueRange = [0, 200]
   unit = 'millisecond'

 # Host-initiated waveform manual trigger output report
 [[applicationCollection.outputReport]]
 id = 0x11

  [[applicationCollection.outputReport.variableItem]]
  usage = ['Haptics', 'Manual Trigger']
  logicalValueRange = [1, 10]

  [[applicationCollection.outputReport.variableItem]]
  usage = ['Haptics', 'Intensity']
  logicalValueRange = [0, 4]

  [[applicationCollection.outputReport.variableItem]]
  usage = ['Haptics', 'Repeat Count']
  logicalValueRange = [0, 5]

  [[applicationCollection.outputReport.variableItem]]
  usage = ['Haptics', 'Retrigger Period']
  logicalValueRange = [0, 1000]
  physicalValueRange = [0, 1000]
  unit = 'millisecond'

  [[applicationCollection.outputReport.variableItem]]
  usage = ['Haptics', 'Waveform Cutoff Time']
  logicalValueRange = [1000, 5000]
  physicalValueRange = [1000, 5000]
  unit = 'millisecond'