一般的ではない HID デバイスへの接続

WebHID API を使用すると、ウェブサイトで代替補助キーボードや珍しいゲームパッドにアクセスできます。

François Beaufort
François Beaufort

ヒューマン インターフェース デバイス(HID)のロングテールには、 新しすぎる、古すぎる、珍しい、キーボードや珍しいゲームパッド システムからアクセス可能なダウンロードします。WebHID API は、この問題を解決するため、 方法をいくつか見ていきましょう。

推奨されるユースケース

HID デバイスは、人間から入力を受け取る、または人間に出力を提供します。デバイスの例 キーボード、ポインティング デバイス(マウス、タッチスクリーンなど)、ゲームパッドが含まれます。 HID プロトコルにより、こうしたデバイスにパソコンでアクセスできるようになります。 接続することもできますウェブ プラットフォームが HID デバイスをサポートしている 大きな収益を得られます

一般的でない HID デバイスにアクセスできないのは、 は代替の補助キーボード(Elgato Stream DeckJabra など)に対応 ヘッドセットX キーなど)、エキゾチックなゲームパッドのサポート。パソコン用に設計されたゲームパッド ゲームパッドの入力(ボタン、ジョイスティック、トリガー)と出力に HID を使用することが多い (LED、ランブル)残念ながら、ゲームパッドの入出力は ウェブブラウザが特定のデバイス用のカスタム ロジックを必要とする場合がよくあります。 このような状況は持続不可能であり、旧来の企業やカスタマー サービスのロングテール 保護します。また、ブラウザは動作の特性に依存します。 特定できます

用語

HID は、レポートとレポート記述子という 2 つの基本的な概念で構成されています。 レポートは、デバイスとソフトウェア クライアントの間で交換されるデータです。 レポート記述子は、デバイスで受信するデータの形式と意味を サポートします。

HID(ヒューマン インターフェース デバイス)は、デバイスから入力を受け取る、または 人間に出力を提供しますまた、HID プロトコルとも呼ばれる、HID プロトコルの標準規格です。 ホストとデバイス間の双方向通信は、ネットワーク間で通信が インストール手順を簡素化できます。HID プロトコルは、 それ以来、他の多くのプロトコルで実装され、 対応しています。

アプリケーションと HID デバイスは、次の 3 種類のレポートを通じてバイナリデータを交換します。

レポートの種類 説明
入力レポート デバイスからアプリに送信されるデータ(ボタンが押された場合など)。
出力レポート アプリケーションからデバイスに送信されるデータ(キーボード バックライトをオンにするリクエストなど)。
機能レポート どちらの方向にも送信できるデータです。形式はデバイスによって異なります。

レポート記述子は、 ダウンロードします構造は階層的で、レポートを個別のユーザーとしてグループ化できます。 含まれている場合は記述子の形式は次のとおりです。 使用されます。

HID 使用状況は、標準化された入力または出力を参照する数値です。 使用状況の値により、デバイスはデバイスの意図された用途と、 レポートの各フィールドの用途に使用します。たとえば、1 つは左側に定義され、 操作できます。使用状況は使用状況ページにも整理されており、 デバイスまたはレポートの大まかなカテゴリを示します。

WebHID API の使用

機能検出

WebHID API がサポートされているかどうかを確認するには、次のコマンドを使用します。

if ("hid" in navigator) {
  // The WebHID API is supported.
}

HID 接続を開く

WebHID API は非同期に設計されているため、ウェブサイトの UI が ブロックします。HID データは受信される可能性があるため、これは重要です。 それを聞く手段が必要です。

HID 接続を開くには、まず HIDDevice オブジェクトにアクセスします。そのためには デバイスの選択を求めるメッセージが navigator.hid.requestDevice()、または navigator.hid.getDevices() から選択してください アクセスが許可されているデバイスのリストが返されます。 使用します。

navigator.hid.requestDevice() 関数は、次のような必須のオブジェクトを受け取ります。 フィルタを定義します。USB ベンダーに接続されたデバイスの照合に使用されます。 ID(vendorId)、USB プロダクト ID(productId)、使用状況ページ 値(usagePage)、使用状況の値(usage)。これらは USB ID リポジトリHID 使用状況の表のドキュメント

この関数から返される複数の HIDDevice オブジェクトは、複数の 同じ物理デバイス上の HID インターフェース。

// Filter on devices with the Nintendo Switch Joy-Con USB Vendor/Product IDs.
const filters = [
  {
    vendorId: 0x057e, // Nintendo Co., Ltd
    productId: 0x2006 // Joy-Con Left
  },
  {
    vendorId: 0x057e, // Nintendo Co., Ltd
    productId: 0x2007 // Joy-Con Right
  }
];

// Prompt user to select a Joy-Con device.
const [device] = await navigator.hid.requestDevice({ filters });
// Get all devices the user has previously granted the website access to.
const devices = await navigator.hid.getDevices();
<ph type="x-smartling-placeholder">
</ph> ウェブサイトに表示された HID デバイスのメッセージのスクリーンショット。
Nintendo Switch Joy-Con を選択するためのユーザー プロンプト

また、オプションの exclusionFilters キーを使用して、 navigator.hid.requestDevice(): ブラウザ選択ツールから一部のデバイスを除外します たとえば 不具合のあることが判明している

// Request access to a device with vendor ID 0xABCD. The device must also have
// a collection with usage page Consumer (0x000C) and usage ID Consumer
// Control (0x0001). The device with product ID 0x1234 is malfunctioning.
const [device] = await navigator.hid.requestDevice({
  filters: [{ vendorId: 0xabcd, usagePage: 0x000c, usage: 0x0001 }],
  exclusionFilters: [{ vendorId: 0xabcd, productId: 0x1234 }],
});

HIDDevice オブジェクトには、デバイスの USB ベンダー ID と製品 ID が含まれます。 あります。その collections 属性は、階層構造で初期化されます。 デバイスのレポート形式に関する説明です。

for (let collection of device.collections) {
  // An HID collection includes usage, usage page, reports, and subcollections.
  console.log(`Usage: ${collection.usage}`);
  console.log(`Usage page: ${collection.usagePage}`);

  for (let inputReport of collection.inputReports) {
    console.log(`Input report: ${inputReport.reportId}`);
    // Loop through inputReport.items
  }

  for (let outputReport of collection.outputReports) {
    console.log(`Output report: ${outputReport.reportId}`);
    // Loop through outputReport.items
  }

  for (let featureReport of collection.featureReports) {
    console.log(`Feature report: ${featureReport.reportId}`);
    // Loop through featureReport.items
  }

  // Loop through subcollections with collection.children
}

HIDDevice デバイスはデフォルトで「閉じた」状態として返されます。Pod の状態であり、 データを送受信できるようになる前に open() を呼び出して開きます。

// Wait for the HID connection to open before sending/receiving data.
await device.open();

入力レポートを受け取る

HID 接続が確立されたら、受信入力を処理できます。 デバイスの "inputreport" イベントをリッスンして、レポートを作成します。これらのイベント HID データを DataView オブジェクト(data)として格納し、そのオブジェクトが属する HID デバイスを指定します。 を(device)、入力レポートに関連付けられた 8 ビットのレポート ID (reportId)。

<ph type="x-smartling-placeholder">
</ph> Nintendo Switch の赤と青の写真。
Nintendo Switch Joy-Con デバイス

前の例の場合、以下のコードは、 Joy-Con Right デバイスでユーザーが押したボタン。 ぜひご自宅で試してみてください。

device.addEventListener("inputreport", event => {
  const { data, device, reportId } = event;

  // Handle only the Joy-Con Right device and a specific report ID.
  if (device.productId !== 0x2007 && reportId !== 0x3f) return;

  const value = data.getUint8(0);
  if (value === 0) return;

  const someButtons = { 1: "A", 2: "X", 4: "B", 8: "Y" };
  console.log(`User pressed button ${someButtons[value]}.`);
});

出力レポートを送信する

出力レポートを HID デバイスに送信するには、そのデバイスに関連付けられた 8 ビットのレポート ID を 出力レポート(reportId)とバイト数を BufferSourcedata)として device.sendReport()。レポートが生成されると、返された Promise は解決されます。 送信しました。HID デバイスがレポート ID を使用しない場合は、reportId を 0 に設定します。

以下の例は Joy-Con デバイスに適用し、その作成方法を示しています 出力レポートを使ってみましょう。

// First, send a command to enable vibration.
// Magical bytes come from https://github.com/mzyy94/joycon-toolweb
const enableVibrationData = [1, 0, 1, 64, 64, 0, 1, 64, 64, 0x48, 0x01];
await device.sendReport(0x01, new Uint8Array(enableVibrationData));

// Then, send a command to make the Joy-Con device rumble.
// Actual bytes are available in the sample below.
const rumbleData = [ /* ... */ ];
await device.sendReport(0x10, new Uint8Array(rumbleData));

機能レポートの送受信

機能レポートは、両方のタイプで送信できる唯一の HID データレポートです。 説明します。HID デバイスや HID アプリケーションで標準化されていない標準を交換できる HID データ。入力 / 出力レポートとは異なり、特徴レポートは受信または 定期的に送信されます。

<ph type="x-smartling-placeholder">
</ph> 黒とシルバーのノートパソコンの写真。
ノートパソコンのキーボード

機能レポートを HID デバイスに送信するには、関連付けられた 8 ビットのレポート ID を 特徴レポート(reportId)とバイトを BufferSourcedata)として device.sendFeatureReport()。レポートが生成されると、返された Promise は解決されます。 送信します。HID デバイスがレポート ID を使用しない場合は、reportId を 0 に設定します。

以下の例では、特徴レポートの使い方と Apple キーボードバックライトデバイスをリクエストして デバイスを開けて点滅させます

const waitFor = duration => new Promise(r => setTimeout(r, duration));

// Prompt user to select an Apple Keyboard Backlight device.
const [device] = await navigator.hid.requestDevice({
  filters: [{ vendorId: 0x05ac, usage: 0x0f, usagePage: 0xff00 }]
});

// Wait for the HID connection to open.
await device.open();

// Blink!
const reportId = 1;
for (let i = 0; i < 10; i++) {
  // Turn off
  await device.sendFeatureReport(reportId, Uint32Array.from([0, 0]));
  await waitFor(100);
  // Turn on
  await device.sendFeatureReport(reportId, Uint32Array.from([512, 0]));
  await waitFor(100);
}

HID デバイスから機能レポートを受け取るには、8 ビットのレポート ID を渡します。 特徴レポート(reportId)に関連付けられた device.receiveFeatureReport()。返された Promise は、 機能レポートのコンテンツを含む DataView オブジェクト。HID が デバイスでレポート ID が使用されていない場合は、reportId を 0 に設定します。

// Request feature report.
const dataView = await device.receiveFeatureReport(/* reportId= */ 1);

// Read feature report contents with dataView.getInt8(), getUint8(), etc...

接続と切断のリッスン

HID デバイスへのアクセスが許可されている場合、ウェブサイトは "connect" をリッスンすることで、接続と切断のイベントをアクティブに受信する と "disconnect" イベント。

navigator.hid.addEventListener("connect", event => {
  // Automatically open event.device or warn user a device is available.
});

navigator.hid.addEventListener("disconnect", event => {
  // Remove |event.device| from the UI.
});

HID デバイスへのアクセス権を取り消す

ウェブサイトで、利用されなくなった HID デバイスにアクセスする権限をクリーンアップできる HIDDevice インスタンスの forget() を呼び出して保持を検討している。対象 たとえば、多くのユーザーと共有のパソコンで使用される教育用ウェブ アプリケーションの場合、 蓄積されたアクセス許可が蓄積されてしまうと、 向上させることができます

1 つの HIDDevice インスタンスで forget() を呼び出すと、すべてのアクセス権が取り消されます 同じ物理デバイス上の HID インターフェースです

// Voluntarily revoke access to this HID device.
await device.forget();

forget() は Chrome 100 以降で利用できるため、この機能に対応しているかどうかをご確認ください 以下でサポートされます。

if ("hid" in navigator && "forget" in HIDDevice.prototype) {
  // forget() is supported.
}

開発のヒント

内部ページ about://device-log を使用すると、Chrome の HID を簡単にデバッグできます。 HID および USB デバイスに関連するすべてのイベントを 1 か所で確認できます。

<ph type="x-smartling-placeholder">
</ph> HID をデバッグするための内部ページのスクリーンショット。
HID をデバッグするための Chrome の内部ページ。

HID デバイスをダンプするには、HID エクスプローラを確認してください。 人が読める形式に変換されます。使用状況の値から各オブジェクトの名前に HID 使用状況。

ほとんどの Linux システムでは、HID デバイスは あります。Chrome で HID デバイスを開けるようにするには、新しい udev コマンドを ルールをご覧ください。/etc/udev/rules.d/50-yourdevicename.rules にファイルを 次の内容が含まれます。

KERNEL=="hidraw*", ATTRS{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"

上記の行の [yourdevicevendor] は、デバイスが Nintendo Switch の場合、057e です。 Joy-Con などです。ATTRS{idProduct} を追加して、より具体的な 適用できます。userplugdev グループのメンバーであることを確認してください。次に、 デバイスを再接続してください。

ブラウザ サポート

WebHID API は、あらゆるデスクトップ プラットフォーム(ChromeOS、Linux、macOS、 (Chrome 89)でリリースされます。

デモ

一部の WebHID デモは web.dev/hid-examples に掲載されています。見てみよう!

セキュリティとプライバシー

仕様の作成者は、Core 強力なウェブ プラットフォーム機能へのアクセスの制御で定義されている原則 あらゆる側面に関与しています。この機能を API は主に、1 つのサービスにのみアクセスを許可する権限モデルによって 1 台につき 1 台までです。ユーザーのプロンプトに応じて、ユーザーは 選択します。

セキュリティのトレードオフについては、セキュリティとプライバシー (WebHID 仕様の考慮事項)セクションを参照してください。

さらに Chrome は、各トップレベル コレクションの使用状況を検査し、 最上位のコレクションに保護された使用法(汎用キーボード、マウスなど)がある場合、 そのウェブサイトで定義したレポートを送受信できなくなります あります保護されている用途の一覧については、公開されています。

セキュリティに影響を及ぼす HID デバイス(FIDO HID デバイスなど)は、 より強力な認証など)は、Chrome でもブロックされます。USB ブロックリストHID ブロックリスト ファイル。

フィードバック

Chrome チームでは、 WebHID API

API 設計について教えてください

API に関して想定どおりに機能していないものはありますか?それとも アイデアを実装するために必要なメソッドやプロパティが足りませんか?

WebHID API の GitHub リポジトリで仕様に関する問題を報告するか、ご意見をお聞かせください 役立ちます

実装に関する問題を報告する

Chrome の実装にバグは見つかりましたか?それとも どうなるでしょうか

WebHID のバグを報告する方法をご確認ください。できるだけ多くの バグを再現するための簡単な手順を提供し、さらに、バグを再現するための コンポーネントBlink>HID に設定します。Glitch が適しているケース 簡単に再現できます。

サポートの気持ちを伝える

WebHID API を使用する予定はありますか?皆様の公開サポートは、Chrome を チームは機能の優先度を判断し、他のブラウザ ベンダーが サポートします。

ハッシュタグを使用して @ChromiumDev にツイートしてください #WebHIDして、ご意見をお聞かせください 使用する場所と方法がわかります。

関連情報

謝辞

この記事をレビューしてくれた Matt ReynoldsJoe Medley に感謝します。 Nintendo Switch の赤と青の写真(Sara Kurfe 取)と、黒と銀のノートパソコン コンピュータの写真、Athul Cyriac Ajay 氏、Unsplash より