WebUSB 用デバイスの作成

WebUSB API を最大限に活用するためのデバイスを構築します。

この記事では、 WebUSB APIAPI 自体の簡単な説明については、USB デバイスへのアクセスに関するページをご参照ください をご覧ください

背景

ユニバーサル シリアル バス(USB)は、 周辺機器をデスクトップ デバイスやモバイル コンピューティング デバイスに接続する。これらに加えて、 バスの電気特性を定義し、その一般的なモデルを デバイスとの通信により、USB の仕様にはデバイスのクラス 仕様。これらは特定のクラスのデバイスの一般的なモデルです。 ストレージ、オーディオ、ビデオ、ネットワークなどをデバイス メーカーが提供し、 説明します。これらのデバイスクラス仕様の利点は、 オペレーティング システム ベンダーは、クラスに基づいて 1 つのドライバを実装できます。 (クラスドライバ)と、そのクラスを実装するデバイスには、 サポートされません。これは、すべてのメーカーが 独自のデバイス ドライバを使用できます。

ただし、これらの標準化されたデバイスクラスのいずれかに適合しないデバイスもあります。 メーカーは代わりに、デバイスに「実装」とラベル付けすることを選択できます。 ベンダー固有のクラス。この場合、オペレーティング システムによって ベンダーのドライバ パッケージで提供される情報に基づいて読み込むドライバ 通常はベンダー ID とプロダクト ID のセットで、 特定のベンダー固有のプロトコルを使用します。

USB のもう一つの機能として、デバイスは複数のインターフェースを 接続されています。各インターフェースでは、 標準化されたクラスにするかベンダー固有にできます。オペレーティング システムによって 各インターフェースは、要求されるデバイスに応じて異なる ドライバです。たとえば、USB ウェブカメラは通常 2 つのインターフェースを提供します。 USB 動画クラス(カメラ用)と USB Audio Class(マイク用)です。オペレーティング システムは、1 つまたは複数のコンテナを "ウェブカメラ ドライバ"代わりに、独立した動画およびオーディオ クラス ドライバを読み込みます。 デバイスの個々の機能を担当します。この インターフェース クラスの構成により柔軟性が向上します。

API の基本

標準 USB クラスの多くには、対応するウェブ API があります。たとえば、 ページで getUserMedia() を使用して Video クラスのデバイスから動画をキャプチャできます。 リッスンすることで、ヒューマン インターフェース(HID)クラスのデバイスから入力イベントを受信する KeyboardEvents または PointerEvents を使用するか、ゲームパッドまたは WebHID API。 すべてのデバイスが標準化されたクラス定義を実装するわけではないのと同様に、すべてのデバイスで デバイスは、既存のウェブ プラットフォーム API に対応する機能を実装しています。日時 そのため WebUSB API では ベンダー固有のインターフェースを要求し、そのインターフェースのサポートを アクセスできるようになります

WebUSB 経由でデバイスにアクセスできるようにするための具体的な要件は、若干異なります。 プラットフォーム間での USB の管理方法の違いによる、 ただし、基本的な要件として、デバイスにデバイスに ドライバがページから制御したいインターフェースを要求します。これは次のいずれかです。 OS ベンダーが提供する汎用クラスドライバ、または OS ベンダーが提供するデバイス ドライバ ベンダー。USB デバイスは複数のインターフェースを提供できるため、各インターフェースは 独自のドライバを持っているため、いくつかのインターフェースを ドライバによって要求され、その他はブラウザからアクセスできるままにしておく必要があります。

たとえば、ハイエンドの USB キーボードは、HID クラス インターフェースを オペレーティング システムの入力サブシステムとベンダー固有の インターフェースを実装する必要があります。この ツールがメーカーのウェブサイトで配信され、ユーザーが マクロキーや照明効果など、デバイスの動作に関する プラットフォーム固有のソフトウェアを インストールする必要はありませんこのようなデバイスの設定記述子は、 次のようになります。

フィールド 説明
構成記述子
0x09 bLength この記述子のサイズ
0x02 bDescriptorType 構成記述子
0x0039 wTotalLength この一連の記述子の合計長
0x02 bNumInterfaces インターフェースの数
0x01 bConfigurationValue 構成 1
0x00 iConfiguration 設定名(なし)
0b1010000 bmAttributes リモート ウェイクアップ機能を備えた自給式デバイス
0x32 bMaxPower 最大電力は 2 mA 単位で表される
インターフェース記述子
0x09 bLength この記述子のサイズ
0x04 bDescriptorType インターフェース記述子
0x00 bInterfaceNumber インターフェース 0
0x00 bAlternateSetting 代替設定 0(デフォルト)
0x01 bNumEndpoints 1 個のエンドポイント
0x03 bInterfaceClass HID インターフェース クラス
0x01 bInterfaceSubClass ブート インターフェースのサブクラス
0x01 bInterfaceProtocol キーボード
0x00 iInterface インターフェース名(なし)
HID 記述子
0x09 bLength この記述子のサイズ
0x21 bDescriptorType HID 記述子
0x0101 bcdHID HID バージョン 1.1
0x00 bCountryCode ハードウェアの対象国
0x01 bNumDescriptors フォローする HID クラス記述子の数
0x22 bDescriptorType レポート記述子タイプ
0x003F wDescriptorLength レポート記述子の全長
エンドポイント記述子
0x07 bLength この記述子のサイズ
0x05 bDescriptorType エンドポイント記述子
0b10000001 bEndpointAddress エンドポイント 1(IN)
0b00000011 bmAttributes 割り込み
0x0008 wMaxPacketSize 8 バイトのパケット
0x0A bInterval 10 ミリ秒間隔
インターフェース記述子
0x09 bLength この記述子のサイズ
0x04 bDescriptorType インターフェース記述子
0x01 bInterfaceNumber インターフェース 1
0x00 bAlternateSetting 代替設定 0(デフォルト)
0x02 bNumEndpoints 2 個のエンドポイント
0xFF bInterfaceClass ベンダー固有のインターフェース クラス
0x00 bInterfaceSubClass
0x00 bInterfaceProtocol
0x00 iInterface インターフェース名(なし)
エンドポイント記述子
0x07 bLength この記述子のサイズ
0x05 bDescriptorType エンドポイント記述子
0b10000010 bEndpointAddress エンドポイント 1(IN)
0b00000010 bmAttributes バルク
0x0040 wMaxPacketSize 64 バイトのパケット
0x00 bInterval 一括エンドポイントの場合はなし
エンドポイント記述子
0x07 bLength この記述子のサイズ
0x05 bDescriptorType エンドポイント記述子
0b00000011 bEndpointAddress エンドポイント 3(出力)
0b00000010 bmAttributes バルク
0x0040 wMaxPacketSize 64 バイトのパケット
0x00 bInterval 一括エンドポイントの場合はなし

構成記述子は、連結された複数の記述子で構成されます。 説明します。それぞれが bLength フィールドと bDescriptorType フィールドで始まるため、 特定できます。1 つ目のインターフェースは HID インターフェースであり、 HID 記述子と、HID 記述子に入力イベントを配信するために使用される単一のエンドポイント OS です。2 つ目のインターフェースは、ベンダー固有のインターフェースです。 デバイスへのコマンドの送信とレスポンスの受信に使用できるエンドポイント 見返りに行われます

WebUSB 記述子

WebUSB はファームウェアを変更しなくても多くのデバイスで動作しますが、 追加機能を有効にするには、デバイスに WebUSB のサポートを示す記述子です。たとえば、デフォルトの デバイスにアクセスしたときにブラウザからユーザーをリダイレクトできるランディング ページ URL 電源に接続されます。

<ph type="x-smartling-placeholder">
</ph> Chrome の WebUSB 通知のスクリーンショット
WebUSB 通知

バイナリ デバイス オブジェクト ストア(BOS)は USB 3.0 で導入されたコンセプトです。 バージョン 2.1 では USB 2.0 デバイスにもバックポートされています。宣言 WebUSB のサポートは、次のプラットフォーム機能を含むことから始まります。 BOS 記述子の記述子:

フィールド 説明
バイナリ デバイスのオブジェクト ストア記述子
0x05 bLength この記述子のサイズ
0x0F bDescriptorType バイナリ デバイスのオブジェクト ストア記述子
0x001D wTotalLength この一連の記述子の合計長
0x01 bNumDeviceCaps BOS 内のデバイス機能記述子の数
WebUSB プラットフォーム機能記述子
0x18 bLength この記述子のサイズ
0x10 bDescriptorType デバイス機能記述子
0x05 bDevCapabilityType プラットフォーム機能記述子
0x00 bReserved
{0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65} PlatformCapablityUUID リトル エンディアン形式の WebUSB プラットフォーム機能記述子 GUID
0x0100 bcdVersion WebUSB 記述子バージョン 1.0
0x01 bVendorCode bWebUSB の bRequest 値
0x01 iLandingPage ランディング ページの URL

プラットフォーム機能 UUID では、これを WebUSB プラットフォーム機能として識別します。 記述子は、デバイスに関する基本情報を提供します。ブラウザの場合 デバイスの詳細情報を取得するため、bVendorCode 値を使用して デバイスに追加のリクエストを発行できます。現在指定されているリクエストは GET_URLURL 記述子を返します。これらは String と同様の 最小バイトで URL をエンコードするように設計されています。URL "https://google.com" の記述子は次のようになります。

フィールド 説明
URL 記述子
0x0D bLength この記述子のサイズ
0x03 bDescriptorType URL 記述子
0x01 bScheme https://
"google.com" URL UTF-8 でエンコードされた URL コンテンツ

デバイスを最初に接続したとき、ブラウザは BOS 記述子を 標準的な GET_DESCRIPTOR コントロール転送を発行します。

bmRequestType bRequest wValue wIndex wLength データ(レスポンス)
0b10000000 0x06 0x0F00 0x0000 * BOS 記述子

通常、このリクエストは 2 回行われます。1 回目は wLength が十分に大きいため、 これにより、ホストは名前を指定せずに wTotalLength フィールドの値を 大規模な転送をコミットし、ディスクリプタ全体の長さが 認識します。

WebUSB プラットフォーム機能記述子の iLandingPage フィールドが ゼロ以外の値を指定すると、ブラウザは WebUSB 固有の GET_URL リクエストを実行します。 bRequestbVendorCode 値に設定してコントロール転送を発行することにより、 プラットフォーム機能記述子から取得し、wValueiLandingPage に設定します。 あります。GET_URL のリクエスト コード(0x02)は wIndex に入れます。

bmRequestType bRequest wValue wIndex wLength データ(レスポンス)
0b11000000 0x01 0x0001 0x0002 * URL 記述子

この場合も、最初に長さを調べるために、このリクエストが 2 回発行されることがあります。 あります。

プラットフォーム固有の考慮事項

一方 WebUSB API は、 USB デバイスのデベロッパーは、 アプリケーションを制御するために必要です。

macOS

macOS の場合、特別な操作は必要ありません。WebUSB を使用するウェブサイトは、 カーネル ドライバまたはカーネル ドライバによって要求されていない できます。

Linux

Linux は macOS に似ていますが、ほとんどのディストリビューションではデフォルトで アクセスを許可する必要があります。udev というシステム デーモンが、 デバイスへのアクセスを許可されたユーザーとグループの割り当てを担います。ルール 指定したベンダーに一致するデバイスの所有権を割り当てます。 プロダクト ID を、アクセス権を持つユーザーの共通のグループである plugdev グループに追加します。 次のとおりです。

SUBSYSTEM=="usb", ATTR{idVendor}=="XXXX", ATTR{idProduct}=="XXXX", GROUP="plugdev"

XXXX は、デバイスの 16 進数のベンダー ID とプロダクト ID に置き換えます。 例:ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e11" は Nexus One にマッチします できます。これらは通常の「0x」なしで記述する必要があります。接頭辞とすべて小文字 必要があります。デバイスの ID を確認するには、次のコマンドを実行します。 ツール lsusb

このルールは、/etc/udev/rules.d ディレクトリ内のファイルに配置する必要があります。 はデバイスが電源に接続されるとすぐに有効になります。再起動する必要はありません。 udev。

Android

Android プラットフォームは Linux をベースとしていますが、 できます。デフォルトでは、ドライバがビルドされていないデバイス ブラウザがオペレーティング システムに取り込むことができます。開発者は ユーザーがサービス アカウントに接続するときに追加の手順が クリックします。ユーザーがデバイスへの応答としてデバイスを選択すると、 requestDevice()。Android は、許可するかどうかを尋ねるプロンプトを表示します。 アクセスできます。このメッセージは、ユーザーがウェブサイトに戻った場合にも再表示されます。 デバイスに接続する権限を持っており、ウェブサイトから open()

さらに、Android の方がパソコンの Linux よりも多くのデバイスにアクセスできる デフォルトで含まれるドライバの数が少なくなるためです。たとえば、 USB - シリアル アダプターによって一般的に実装される USB CDC-ACM クラスです。 は、Android SDK にはシリアル デバイスとの通信用の API ではありません。

ChromeOS

ChromeOS も Linux をベースとしており、変更は不要 変更します。permission_scheduler サービスは USB へのアクセスを制御します。 少なくとも 2 台以上の認証情報があれば、ブラウザは 1 つの未申請インターフェースがあります。

Windows

Windows ドライバモデルには追加要件があります。 ユーザー アプリケーションから USB デバイスを開く機能以上では、 ドライバがロードされていなくてもデフォルトで適用されます。代わりに、特別な という 2 つのドライバがあります。このドライバは、インタフェースとして アプリがデバイスへのアクセスに使用する デバイスが決まりますこれを行うには、カスタム システムにインストールされている、またはデバイスに改変されたドライバ情報ファイル(INF) Microsoft OS 互換性記述子を提供するファームウェアを 列挙できます。

ドライバ情報ファイル(INF)

デバイスに遭遇した際の対処方法を Windows に指示するドライバ情報ファイル 説明します。ユーザーのシステムにはすでに WinUSB ドライバが組み込まれているため、 あとは、INF ファイルでベンダーとプロダクト ID を関連付けるだけです。 新しいインストール ルールが適用されます。以下のファイルは基本的な例です。保存する 拡張子が .inf のファイルで、「X」でマークされたセクションを変更してから、 クリックして [インストール] を選択します。選択できます。

[Version]
Signature   = "$Windows NT$"
Class       = USBDevice
ClassGUID   = {88BAE032-5A81-49f0-BC3D-A4FF138216D6}
Provider    = %ManufacturerName%
CatalogFile = WinUSBInstallation.cat
DriverVer   = 09/04/2012,13.54.20.543

; ========== Manufacturer/Models sections ===========

[Manufacturer]
%ManufacturerName% = Standard,NTx86,NTia64,NTamd64

[Standard.NTx86]
%USB\MyCustomDevice.DeviceDesc% = USB_Install,USB\VID_XXXX&PID_XXXX

[Standard.NTia64]
%USB\MyCustomDevice.DeviceDesc% = USB_Install,USB\VID_XXXX&PID_XXXX

[Standard.NTamd64]
%USB\MyCustomDevice.DeviceDesc% = USB_Install,USB\VID_XXXX&PID_XXXX

; ========== Class definition ===========

[ClassInstall32]
AddReg = ClassInstall_AddReg

[ClassInstall_AddReg]
HKR,,,,%ClassName%
HKR,,NoInstallClass,,1
HKR,,IconPath,%REG_MULTI_SZ%,"%systemroot%\system32\setupapi.dll,-20"
HKR,,LowerLogoVersion,,5.2

; =================== Installation ===================

[USB_Install]
Include = winusb.inf
Needs   = WINUSB.NT

[USB_Install.Services]
Include = winusb.inf
Needs   = WINUSB.NT.Services

[USB_Install.HW]
AddReg = Dev_AddReg

[Dev_AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"

; =================== Strings ===================

[Strings]
ManufacturerName              = "Your Company Name Here"
ClassName                     = "Your Company Devices"
USB\MyCustomDevice.DeviceDesc = "Your Device Name Here"

[Dev_AddReg] セクションでは、デバイスの DeviceInterfaceGUID のセットを構成します。 ダウンロードしますアプリで GUID を使用するには、すべてのデバイス インターフェースに GUID が必要です。 Windows API でネットワークを検索して接続します。New-Guid PowerShell を使用する ランダム GUID を生成します。

開発目的の場合は、Zadig ツールを利用することで、 USB インタフェース用にロードされたドライバを WinUSB ドライバに置き換えます。

Microsoft OS 互換性記述子

上記の INF ファイルを使用する方法は、すべてのファイルを構成し、 マシンに事前に転送されますWindows 8.1 以降の場合は、代替機能として カスタム USB 記述子を使用します。これらの記述子を使用すると、 システムに最初に接続したとき、Windows オペレーティング システムに 通常は INF ファイルに含まれます。

WebUSB 記述子を設定すると、Microsoft の OS を簡単に追加できます。 記述することもできます。まず、このファイルで BOS 記述子を拡張します。 追加のプラットフォーム機能記述子。必ず wTotalLength を更新してください これを考慮するには bNumDeviceCaps を使用します。

フィールド 説明
Microsoft OS 2.0 プラットフォームの機能記述子
0x1C bLength この記述子のサイズ
0x10 bDescriptorType デバイス機能記述子
0x05 bDevCapabilityType プラットフォーム機能記述子
0x00 bReserved
{0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F} PlatformCapablityUUID リトル エンディアン形式の Microsoft OS 2.0 プラットフォーム互換性記述子 GUID
0x06030000 dwWindowsVersion Windows の最小互換バージョン(Windows 8.1)
0x00B2 wMSOSDescriptorSetTotalLength 記述子セットの合計長
0x02 bMS_VendorCode その他の Microsoft 記述子を取得するための bRequest 値
0x00 bAltEnumCode デバイスは代替の列挙に対応していません

WebUSB 記述子と同様に、使用する bRequest 値を選択する必要があります。 制御転送を制御します。この例では、 0x02wIndex に配置された 0x07 は、Microsoft OS を取得するコマンドです。 デバイスからの 2.0 記述子セット。

bmRequestType bRequest wValue wIndex wLength データ(レスポンス)
0b11000000 0x02 0x0000 0x0007 * MS OS 2.0 記述子セット

USB デバイスは複数の機能を持つことができるため、記述子の最初の部分は set は、後続のプロパティが関連付けられている関数を示します。「 複合デバイスのインターフェース 1 を設定する例を以下に示します。この記述子は、 このインターフェースに関する 2 つの重要な情報があります互換性のある ID 記述子は、このデバイスが WinUSB に対応していることを Windows に伝えます。 ドライバです。レジストリ プロパティ記述子は 上の INF の例の [Dev_AddReg] セクションで、レジストリ プロパティを この関数にデバイス インターフェース GUID を割り当てます。

フィールド 説明
Microsoft OS 2.0 記述子セット ヘッダー
0x000A wLength この記述子のサイズ
0x0000 wDescriptorType 記述子セットのヘッダー記述子
0x06030000 dwWindowsVersion Windows の最小互換バージョン(Windows 8.1)
0x00B2 wTotalLength 記述子セットの合計長
Microsoft OS 2.0 構成サブセット ヘッダー
0x0008 wLength この記述子のサイズ
0x0001 wDescriptorType 構成サブセットのヘッダーの記述。
0x00 bConfigurationValue 構成 1 に適用されます(構成にかかわらず、0 からインデックス付けされます) 通常、インデックス番号は 1)
0x00 bReserved 0 に設定する必要があります。
0x00A8 wTotalLength このヘッダーを含むサブセットの合計長
Microsoft OS 2.0 関数サブセット・ヘッダー
0x0008 wLength この記述子のサイズ
0x0002 wDescriptorType 関数のサブセットのヘッダー記述子
0x01 bFirstInterface 関数の最初のインターフェース
0x00 bReserved 0 に設定する必要があります。
0x00A0 wSubsetLength このヘッダーを含むサブセットの合計長
Microsoft OS 2.0 互換 ID 記述子
0x0014 wLength この記述子のサイズ
0x0003 wDescriptorType 互換性のある ID 記述子
"WINUSB\0\0" CompatibileID 8 バイトにパディングされた ASCII 文字列
"\0\0\0\0\0\0\0\0" SubCompatibleID 8 バイトにパディングされた ASCII 文字列
Microsoft OS 2.0 レジストリのプロパティ記述子
0x0084 wLength この記述子のサイズ
0x0004 wDescriptorType レジストリプロパティ記述子
0x0007 wPropertyDataType REG_MULTI_SZ
0x002A wPropertyNameLength プロパティ名の長さ
"DeviceInterfaceGUIDs\0" PropertyName UTF-16LE でエンコードされた null 終端を持つプロパティ名
0x0050 wPropertyDataLength プロパティ値の長さ
"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\0\0" PropertyData GUID と 2 つの null 終端文字(UTF-16LE でエンコード)

Windows がこの情報をデバイスに照会するのは 1 回だけです。デバイスが動作している場合 有効な記述子で応答しない場合、次回 デバイスが接続されました。Microsoft は USB デバイス レジストリのリストを提供 Entries は、デバイスの列挙時に作成されるレジストリ エントリを記述するものです。日時 テストでは、デバイス用に作成されたエントリを削除して、Windows に読み取りを強制的に試みます。 使用します。

これらの機能の使用方法について詳しくは、Microsoft のブログ投稿をご覧ください。 使用します。

両方の WebUSB を含む WebUSB 対応デバイスを実装するコード例 記述子と Microsoft OS 記述子は、以下のプロジェクトにあります。