このトピックでは、USB ETW と Netmon を使用して、Windows で認識されない USB デバイスのトラブルシューティングを行う方法の例を示します。
この例では、デバイスを接続し、デバイス マネージャーやユーザー インターフェイス (UI) の他の部分で不明なデバイスとして表示されています。 ハードウェア ID は USB\UNKNOWN でした。 さらに診断するために、デバイスを取り外し、ETW トレースを開始し、デバイスをもう一度接続しました。 デバイスが不明なデバイスとして表示された後、トレースを停止しました。
不明なデバイスの問題について
不明な USB デバイスの問題をデバッグするには、ユーザーがデバイスをシステムに接続したときに、USB ドライバー スタックがデバイスを列挙するために何を行うかを理解するのに役立ちます。 USB 列挙の詳細については、「USB スタックでデバイスを列挙する方法」というタイトルのブログ投稿を参照してください。
通常、USB ドライバー スタックがデバイスの列挙に失敗した場合でも、ハブ ドライバーはデバイスの到着を Windows に報告し、USB デバイスはデバイス マネージャーで不明なデバイスとしてマークされます。 デバイスには、USB\VID_0000&PID_0000 のデバイス ID と、USB\UNKNOWN のハードウェア ID と互換性のある ID があります。 次のイベントにより、USB ハブ ドライバーは、不明なデバイスとして USB デバイスを列挙します。
- 列挙中にポート リセット要求がタイムアウトしました。
- USB デバイスのアドレスの設定要求に失敗しました。
- USB デバイスのデバイス記述子の要求に失敗しました。
- USB デバイス記述子の形式が正しくなされておらず、検証に失敗しました。
- 構成記述子の要求に失敗しました。
- USB 構成記述子の形式が正しくなされておらず、検証に失敗しました。
Windows 7 では、列挙に失敗した不明なデバイスは、デバイス マネージャーでエラー コード 43 でマークされます。
デバイス マネージャーでデバイスがエラー コード 28 でマークされている場合、デバイスは正常に列挙されましたが、まだ不明なデバイスです。 このエラー コードは、列挙中にデバイスが製品 ID 文字列を提供しておらず、Windows がドライバーをインストールするデバイスの一致する INF を見つけられなかったことを示します。
イベント トレース分析の開始
これはデバイスの障害であるため、USB パーサーと共に Netmon を使用してログ ファイルを分析することをお勧めします。
イベント トレース ログを表示するには
Netmon を実行し、[ ファイル] -> [Open -> Capture] をクリックし、ファイルを選択します。
[フレームの概要] ウィンドウで最初のイベントを選択します。このイベントには SystemTrace という説明があります。 この画像は、最初のイベントを選択したときの画面の外観を示しています。
Netmon で表示される列をカスタマイズするには、列名を右クリックし、[列の選択] を 選択します。
SystemTrace 型として識別される最初のイベントには、ログに関する一般的な情報が含まれています。 [フレームの詳細] ウィンドウで情報ツリーを展開すると、失われたイベントの数やトレースの開始時刻などの情報を表示できます。
USB デバイスイベントの概要
イベント 2 は、ログ内の最初の USB イベントです。 このイベントとそれ以降のいくつかのイベントでは、トレースを開始したときにシステムに接続された USB ホスト コントローラー、ハブ、およびデバイスについて説明します。 このイベント グループは、デバイスの概要イベントと呼ぶか、概要イベントのみを呼び出すことができます。 最初のイベントと同様に、概要イベントではドライバーアクティビティは記述されません。 概要イベントは、ログ セッションの開始時にデバイスの状態を記録します。 その他のイベントは、バス上で発生している、クライアント ドライバーまたはシステムとの対話、または内部状態の変更を表します。
USB ハブと USB ポートドライバーの両方が概要イベントをログに記録します。 イベントを記録したドライバーは、[プロトコル名] 列で識別されます。 たとえば、USB ポート ドライバーによってログに記録されるイベントには、USBPort_MicrosoftWindowsUSBPORTプロトコル名があります。 USB イベント トレースには、通常、一連のポート概要イベントの後にハブの概要イベントのシーケンスが含まれます。 USB ポートと USB ハブの概要イベントの多くは、説明に "Information" または "Attributes" という単語が含まれています。
概要イベントの終了を特定するにはどうすればよいですか? ログの開始時に USB ハブ イベント間でタイムスタンプ パターンに重大な中断がある場合、その中断はおそらくデバイスの概要の最後です。 それ以外の場合、USB ハブ イベントの後の最初の USB ポート イベントは、最初の非サマリー イベントである可能性があります。 次のページの図 3 は、このサンプル トレースの最初の非サマリー イベントを示しています。
この例では、トレースを開始したときに対象のデバイスがシステムに接続されていないため、ここではデバイスの概要イベントをスキップできます。
イベントの説明とデータ ペイロード
サンプル ログでは、デバイスの概要イベントの後の最初のイベントは、USB Hub Wait Wake IRP Completed イベントです。 デバイスを接続し、ホスト コントローラーまたはハブが応答して目を覚ましています。 ウェイクアップしているコンポーネントを特定するには、イベントのデータを確認します。 データは[フレームの詳細]ペインに表示され、ツリー構造で約次の形式で表示されます。
Frame information
ETW event header information
ETW event descriptor (Constant information about the event ID such
as error level)
Event payload (Data logged at the time of the event)
Name of a USB-specific structure
Structure members and their values (Types: numbers, strings,
or arrays)
...
USB Hub Wait Wake IRP Completed イベントのペイロード データを展開すると、fid_USBHUB_Hubという名前の ETW 構造体が表示されます。 構造体の名前には、次のコンポーネントがあります。
任期 | 説明 |
---|---|
fid_ | USB ETW 構造体の一般的なプレフィックス。 |
USBHUB_ | USB ハブ ドライバーがイベントをログに記録したことを示します。 |
文字列の残りの部分 | 構造体のデータが記述するオブジェクトの名前。 このイベントの場合は、ハブ オブジェクトです。 |
USB ハブ ドライバーは、usb ハブを記述する fid_USBHUB_Hub 構造を使用します。 データ ペイロードにこのハブ構造を持つイベントはハブを参照し、構造の内容を使用して特定のハブを識別できます。 図 4 は、[フレームの詳細] ウィンドウを示しています。 fid_USBHUB_Hub 構造が展開され、フィールドが表示されています。
ハブ構造は、USB ETW イベントに一般的に表示される他の 2 つの構造体とよく似ています:fid_USBHUB_Device と fid_USBPORT_Device。 次の重要なフィールドは、3 つの構造すべてに共通です。
フィールド | 説明 |
---|---|
fid_idVendor | デバイスの USB ベンダー ID (VID) |
fid_idProduct | デバイスの USB 製品 ID (PID) |
fid_PortPath | USB デバイスが接続されている 1 ベースのハブ ポート番号の一覧。 リスト内のポート番号の数は、 PortPathDepth フィールドに含まれています。 ルート ハブ デバイスの場合、この一覧はすべてゼロです。 ルート ハブ ポートに直接接続されている USB デバイスの場合、PortPath[0] の値は、デバイスが接続されているポートのルート ハブポート番号です。 |
1 つ以上の追加の USB ハブを介して接続されている USB デバイスの場合、ハブ ポート番号の一覧はルート ハブ ポートから始まり、追加のハブ (ルート ハブからの距離順) で続行されます。 ゼロは無視します。 例えば次が挙げられます。
サンプル値 | 説明 |
---|---|
[0, 0, 0, 0, 0, 0] | このイベントは、ルート ハブ (PC 上のポート、USB ホスト コントローラーによって直接制御されるポート) を指します。 |
[3, 0, 0, 0, 0, 0] | イベントは、ルート ハブのポート番号 3 に接続されているハブまたはデバイスを指します。 |
[3, 1, 0, 0, 0, 0] | ハブは、ルート ハブのポート 3 に接続されています。 イベントは、この外部ハブのポート 1 に接続されているハブまたはデバイスを指します。 |
関心のあるデバイスのポート パスを監視する必要があります。 デバイスが列挙されている場合、VID と PID は不明であり、0 としてログに記録されます。 VID と PID は、リセットや一時停止などの一部の低レベルのデバイス要求では表示されません。 これらの要求は、デバイスが接続されているハブに送信されます。
このサンプル ログでは、Wait Wake completion イベントには 6 つのゼロを含むポート パスがあります。 このイベントは、ルート ハブでの Wait Wake アクションを示します。 これは論理的な理由です。デバイスをルート ハブ ポートに接続したため、ルート ハブが起動しています。
USB Netmon フィルター
時間がある場合は、ログの各イベントを時系列で調べることができます。 経験があっても、イベントの説明の一覧をスキャンして重要なイベントをすばやく特定することは困難です。 不明なデバイスの原因をより迅速に見つけるには、Netmon フィルター機能を使用できます。
USB エラー フィルター
Netmon で USB エラー フィルターをアクティブにするには、[フィルター] -> [表示フィルター] -> [読み込みフィルター] -> [標準フィルター] -> [USB -> USB Hub エラー] をクリックし、[表示フィルター] ウィンドウで [適用] をクリックします。
USB エラー フィルターは、次の表に示す条件を満たすイベントのみにイベントの一覧を絞り込みます。
テキストをフィルター処理する | 説明 |
---|---|
(USBPort_MicrosoftWindowsUSBUSBPORT AND NetEvent.Header.Descriptor.Opcode == 34) | オペコード 34 を持つ USB ポート イベントはポート エラーです。 |
(USBHub_MicrosoftWindowsUSBUSBHUB AND NetEvent.Header.Descriptor.Opcode == 11) | オペコード 11 を持つ USB ハブ イベントはハブ エラーです。 |
(NetEvent.Header.Descriptor.Level == 0x2) | 通常、レベル0x2を持つイベントはエラーです。 |
(USBHub_MicrosoftWindowsUSBUSBHUB AND NetEvent.Header.Descriptor.Id == 210) | ID 210 の USB ハブ イベントは、「USBハブ例外が記録された」イベントです。 詳細については、「 エラー イベントと状態コードについて」を参照してください。 |
この図は、サンプル トレース ログに USB エラー フィルターを適用した後、[ フレームの概要 ] ウィンドウに表示されるイベントの小さなセットを示しています。
一連のエラーの概要を確認するには、各エラー イベントを簡単に確認できます。 観察すべき重要なフィールドには、 fid_NtStatus、 fid_UsbdStatus、 およびfid_DebugTextが含まれます。 詳細については、「 エラー イベントと状態コードについて」を参照してください。 フィルターをオフにするには、[フィルターの表示] ウィンドウの [削除] ボタンをクリックします。
カスタム Netmon フィルター
Netmon でカスタム フィルターを作成できます。 最も簡単な方法は、次のいずれかの方法で画面上のデータからフィルターを作成することです。
- [フレームの詳細] ウィンドウでフィールドを右クリックし、[選択した値を表示フィルターに追加] を選択します。
- [フレームサマリー]ペインでフィールドを右クリックし、[フィールド名]を[表示フィルタ]に追加を選択します。
演算子 (OR、AND、=など) とフィルター値を変更して、適切なフィルター式を作成できます。
エラー イベントと状態コードについて
不明なデバイスの例では、ほとんどの USB ハブ例外には CreateDeviceFailure の fid_DebugText データがあります。 例外がどの程度深刻であるかは明らかではありませんが、デバッグ テキストには原因に関するヒントが示されます。新しいデバイスに関連する操作が失敗しました。 ここでは、隣接する Create Device Failed イベントが冗長であると仮定します。 最後の 2 つの例外は、CreateDeviceFailure_PopupとGenErr_UserIoctlFailedです。 ポップアップ例外は、ユーザーに公開されたエラーのように聞こえますが、これらのエラーはすべて、不明なデバイスの問題に関連している可能性があります。
USB エラー イベントやその他のイベントには、問題に関する貴重な情報を提供する状態値がデータに含まれています。 状態の値に関する情報は、次の表のリソースを使用して確認できます。
状態のタイプ | リソース |
---|---|
fid_NtStatus | NTSTATUS 値を参照してください。 |
USB 要求ブロック (URB) またはfid_UsbdStatusの状態フィールド | Windows Driver Kit (WDK) の inc\api\usb.h で値をUSBD_STATUSとして検索します。 USBD_STATUSを使用することもできます。 このトピックでは、シンボリック名と、USBD_STATUS値の意味を示します。 |
問題イベントからの逆方向の読み取り
エラー イベントの前にログに記録されるイベントは、エラーの原因に関する重要な手掛かりとなる可能性があります。 不明なデバイスの根本原因を特定するには、エラーの前にログに記録されたイベントを確認する必要があります。 この例では、CreateDeviceFailure_Popup イベント (2 番目から最後の例外) から後方に向かって見始めます。 USB エラー フィルターが有効な状態でこのイベントを選択し、[表示フィルター] ウィンドウで [削除] をクリックします。 USB エラー フィルターは引き続き [表示フィルター ] ウィンドウに表示され、後で再適用できます。 ただし、フィルターが無効になり、[ フレームの概要 ] ウィンドウに、この画像に示すようにすべてのイベントが表示されます。
CreateDeviceFailure_Popup イベントの直前にログに記録される 2 つのイベントは、ディスパッチと USB コントロール転送の完了です。 fid_USBPORT_Device ポート パス フィールドは両方のイベントで 0 で、転送のターゲットがルート ハブであることを示します。 完了イベントのfid_USBPORT_URB_CONTROL_TRANSFER構造では、状態は 0 (USBD_STATUS_SUCCESS) であり、転送が成功したことを示します。 前のイベントの調査を続行します。
次の 2 つの前のイベントは、前に調べた 4 番目 (最後の) Create Device Failed イベントと 4 番目 (最終) CreateDeviceFailure 例外です。
前の次のイベントは Endpoint Close です。 このイベントは、エンドポイントが使用できなくなったことを意味します。 イベント データは、デバイスとそのデバイス上のエンドポイントの両方を記述します。 デバイス のポート パスは [1, 0, 0, 0, 0, 0] です。 トレースを実行したシステムには、ホスト コントローラー (ルート ハブ) と接続していたデバイスのみが含まれているため、このポート パスではハブは記述されません。 閉じたエンドポイントは、接続した単一のデバイス上にある必要があります。これで、デバイスのパスが 1 であることがわかります。 以前に発生した問題が原因で、ドライバーによってデバイスのエンドポイントにアクセスできなくなった可能性があります。 前のイベントの調査を続行します。
次の前のイベントは、完了した USB コントロール転送です。 イベント データは、転送のターゲットがデバイスであることを示しています (ポート パスは 1)。 fid_USBPORT_Endpoint_Descriptor構造体は、エンドポイントのアドレスが 0 であることを示すので、これは USB で定義された既定の制御エンドポイントです。 URB の状態が0xC0000004。 状態が 0 ではないため、転送は成功しなかった可能性があります。 このUSBD_STATUS値の詳細については、「usb.h」および「 エラー イベントと状態コードについて」を参照してください。
#define USBD_STATUS_STALL_PID ((USBD_STATUS)0xC0000004L)
意味: デバイスがストール パケット識別子を返しました。 エンドポイントによって停止したリクエストは何ですか? イベントに対してログに記録された他のデータは、要求が標準のデバイス制御要求であることを示します。 解析された要求を次に示します。
Frame: Number = 184, Captured Frame Length = 252, MediaType = NetEvent
+ NetEvent:
- MicrosoftWindowsUSBUSBPORT: Complete Internal URB_FUNCTION_CONTROL_TRANSFER
- USBPORT_ETW_EVENT_COMPLETE_INTERNAL_URB_FUNCTION_CONTROL_TRANSFER: Complete Internal URB_FUNCTION_CONTROL_TRANSFER
+ fid_USBPORT_HC:
+ fid_USBPORT_Device:
+ fid_USBPORT_Endpoint:
+ fid_USBPORT_Endpoint_Descriptor:
+ fid_URB_Ptr: 0x84539008
- ControlTransfer:
+ Urb: Status = 0xc0000004, Flags 0x3, Length = 0
- SetupPacket: GET_DESCRIPTOR
+ bmRequestType: (Standard request) 0x80
bRequest: (6) GET_DESCRIPTOR
Value_DescriptorIndex: 0 (0x0)
Value_DescriptorType: (1) DEVICE
_wIndex: 0 (0x0)
wLength: 64 (0x40)
bRequest (GET_DESCRIPTOR) と Value_DescriptorType (DEVICE) を組み合わせると、要求が get-device 記述子であったと判断できます。
USB 列挙を続行するには、デバイスがデバイス記述子を使用してこの要求に応答している必要があります。 代わりに、デバイスが要求をストールしたため、列挙が失敗しました。 そのため、4 つのデバイス作成エラーはすべて、デバイス記述子の要求がストールしたために発生しました。 列挙に失敗し、デバイスがデバイス記述子の要求を完了していないために列挙が失敗したため、デバイスが不明であると判断しました。