Поделиться через


Пример: устранение неполадок с неизвестным USB-устройством с помощью трассировки событий Windows и Netmon

В этом разделе приведен пример использования USB ETW и Netmon для устранения неполадок USB-устройства, которое windows не распознает.

В этом примере мы подключили устройство, и оно появилось как неизвестное устройство в диспетчер устройств и других частях пользовательского интерфейса. Идентификатор оборудования — USB\UNKNOWN. Для дальнейшей диагностики мы отключили устройство, начали трассировку трассировки событий Windows и снова подключили устройство. После того как устройство появилось как неизвестное, мы остановили трассировку.

Сведения о проблеме с неизвестным устройством

Для отладки неизвестной проблемы с USB-устройством необходимо понять, что делает стек драйверов USB для перечисления устройства, когда пользователь подключает его к системе. Сведения о перечислении USB см. в записи блога How does USB stack enumerate a device?

Как правило, если стеку USB-драйвера не удается перечислить устройство, драйвер концентратора по-прежнему сообщает о поступлении устройства в Windows, а USB-устройство помечается как неизвестное устройство в диспетчер устройств. Устройство имеет идентификатор устройства USB\VID_0000&PID_0000 и идентификатор оборудования и совместимый идентификатор USB\UNKNOWN. Следующие события приводят к тому, что драйвер USB-концентратора перечисляет USB-устройство как неизвестное устройство:

  • Время ожидания запроса на сброс порта истекло во время перечисления.
  • Не удалось выполнить запрос на установка адреса для USB-устройства.
  • Запрос дескриптора устройства USB-устройства завершился ошибкой.
  • Дескриптор USB-устройства был неправильно сформирован и не прошел проверку.
  • Сбой запроса дескриптора конфигурации.
  • Дескриптор конфигурации USB был неправильно сформирован и не прошел проверку.

В Windows 7 неизвестные устройства, которые не выполняют перечисление, помечаются кодом сбоя 43 в диспетчер устройств.

Если устройство отмечено кодом сбоя 28 в диспетчер устройств, оно успешно перечислено, но по-прежнему неизвестно. Этот код сбоя указывает, что устройство не предоставило строку идентификатора продукта во время перечисления, и Windows не удалось найти соответствующий INF-файл для устройства, чтобы установить драйвер.

Запуск анализа трассировки событий

Так как это сбой устройства, рекомендуется использовать Netmon с usb-анализатором для анализа файла журнала.

Просмотр журнала трассировки событий

  1. Запустите Netmon, щелкните Файл —> Открыть —> Запись, а затем выберите файл.

  2. Выберите первое событие в области Сводка кадров с описанием SystemTrace. На этом изображении показано, как выглядит экран при выборе первого события.

    Снимок экрана: окно Microsoft Network Monitor после выбора первого события.

  3. Чтобы настроить столбцы, отображаемые в Netmon, щелкните правой кнопкой мыши имя столбца и выберите пункт Выбрать столбцы.

  4. Первое событие, которое определяется как тип SystemTrace, содержит общие сведения о журнале. Вы можете развернуть дерево сведений в области Сведения о фрейме , чтобы просмотреть такие сведения, как количество потерянных событий и время начала трассировки.

События сводки USB-устройства

Событие 2 — это первое событие USB в журнале. Это и несколько последующих событий описывают контроллеры USB-узла, концентраторы и устройства, которые были подключены к системе при запуске трассировки. Эту группу событий можно назвать сводной событиями устройства или просто событиями сводки. Как и первое событие, события сводки не описывают действия драйвера. Сводные события записывают состояние устройств в начале сеанса ведения журнала. Другие события представляют собой что-то, что происходит в шине, взаимодействие с драйверами клиента или системой, а также изменения внутреннего состояния.

Usb-концентратор и драйверы USB-портов регистрируют сводные события. Драйвер, который зарегистрировал событие, определяется в столбце Имя протокола. Например, событие, зарегистрированное драйвером USB-порта, имеет имя протокола USBPort_MicrosoftWindowsUSBPORT. Трассировка событий USB обычно содержит последовательность сводных событий портов, за которой следует последовательность событий сводки концентратора. Многие из сводных событий USB-порта и USB-концентратора содержат слова "Информация" или "Атрибуты".

Как определить конец событий сводки? Если в начале журнала в шаблоне меток времени между событиями USB-концентратора имеется значительный перерыв, вероятно, это конец сводки устройства. В противном случае первое событие USB-порта после любых событий USB-концентратора, скорее всего, будет первым событием без сводки. На рисунке 3 на следующей странице показано первое не сводное событие в этом примере трассировки.

В этом примере интересующее устройство не было подключено к системе, когда мы запустили трассировку, поэтому на данный момент можно пропустить сводные события устройства.

Снимок экрана: устройство, выбранное в разделе

Описание события и полезные данные

В примере журнала первым событием после сводных событий устройства является событие ожидания пробуждения usb Hub 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)
    ...

Разверните данные полезных данных для события IRP ожидания пробуждения USB-концентратора, и вы увидите структуру трассировки событий Windows с именем fid_USBHUB_Hub. Имя структуры состоит из следующих компонентов:

Термин Описание
Fid_ Типичный префикс для структуры ТРАССИРОВКИ СОБЫТИЙ USB.
USBHUB_ Указывает, что драйвер USB-концентратора зарегистрировал событие.
Остальная часть строки Имя объекта, описываемого данными структуры. Для этого события это объект Hub.

Драйвер USB-концентратора использует структуру fid_USBHUB_Hub для описания USB-концентратора. События, имеющие эту структуру концентратора в полезных данных, ссылаются на концентратор, и мы можем определить конкретный концентратор с помощью содержимого структуры. На рисунке 4 показана область Сведения о фрейме с развернутой структурой fid_USBHUB_Hub для отображения полей.

Microsoft Network Monitor — сведения о фрейме.

Структура концентратора очень похожа на две другие структуры, которые обычно отображаются в событиях ТРАССИРОВКИ СОБЫТИЙ USB: fid_USBHUB_Device и fid_USBPORT_Device. Следующие важные поля являются общими для всех трех структур:

Поле Описание
fid_idVendor Идентификатор поставщика USB (VID) устройства
fid_idProduct Идентификатор продукта USB (PID) устройства
fid_PortPath Список номеров портов концентратора, через которые подключено USB-устройство. Число номеров портов в списке содержится в поле PortPathDepth . Для устройств корневого концентратора этот список содержит все нули. Для USB-устройства, подключенного непосредственно к порту корневого концентратора, значение в PortPath[0] — это номер порта корневого концентратора порта, к которому подключено устройство.

Для USB-устройства, подключенного через один или несколько дополнительных USB-концентраторов, список номеров портов концентратора начинается с порта корневого концентратора и продолжается с дополнительных концентраторов (в порядке расстояния от корневого концентратора). Игнорируйте нули. Пример:

Образец значения Описание
[0, 0, 0, 0, 0, 0] Это событие ссылается на корневой концентратор (порт на компьютере, непосредственно управляемый контроллером узла USB).
[3, 0, 0, 0, 0, 0] Это событие ссылается на концентратор или устройство, подключенное к порту корневого концентратора с номером 3.
[3, 1, 0, 0, 0, 0] Концентратор подключается к порту 3 корневого концентратора. Это событие ссылается на концентратор или устройство, подключенное к порту 1 этого внешнего концентратора.

Следует отслеживать пути к портам любых интересующих устройств. При перечислении устройства VID и PID неизвестны и регистрируются как 0. VID и PID не отображаются во время некоторых низкоуровневых запросов устройства, таких как сброс и приостановка. Эти запросы отправляются в концентратор, к которому подключено устройство.

В нашем примере журнала событие завершения ожидания пробуждения имеет путь к порту с шестью нулями. Событие указывает на действие Ожидания пробуждения в корневом концентраторе. Это логично из-за наших действий: мы подключили устройство к порту корневого концентратора, чтобы корневой концентратор просыпался.

Фильтры USB Netmon

Вы можете просмотреть каждое событие в журнале в хронологическом порядке, если у вас есть время. Даже имея опыт, трудно быстро определить важные события путем сканирования списка описаний событий. Чтобы быстрее найти причину неизвестного устройства, можно использовать функцию фильтра Netmon.

Фильтр ошибок USB

Чтобы активировать фильтр ошибок USB в Netmon, щелкните Фильтр отображения —>> Фильтр загрузки —> Стандартные фильтры —> ОШИБКИ USB — USB-концентратора>, а затем нажмите кнопку Применить в области Фильтр отображения.

Фильтр ошибок USB сужает список событий только теми, которые соответствуют критериям, приведенным в следующей таблице.

Фильтрация текста Описание
(USBPort_MicrosoftWindowsUSBUSBPORT AND NetEvent.Header.Descriptor.Opcode == 34) События USB-порта с кодом операции 34 являются ошибками порта.
(USBHub_MicrosoftWindowsUSBUSBHUB AND NetEvent.Header.Descriptor.Opcode == 11) События концентратора USB с кодом операции 11 являются ошибками концентратора.
(NetEvent.Header.Descriptor.Level == 0x2) События с уровнем 0x2 обычно являются ошибками.
(USBHub_MicrosoftWindowsUSBUSBHUB AND NetEvent.Header.Descriptor.Id == 210) События концентратора USB с идентификатором 210 — это события "Зарегистрированные исключения USB-концентратора". Дополнительные сведения см. в разделе Основные сведения о событиях ошибок и кодах состояния.

На этом изображении показан меньший набор событий, которые отображаются в области Сводка по кадрам после применения фильтра ошибок USB к нашему образцу журнала трассировки.

Снимок экрана: набор событий в области

Чтобы просмотреть общие сведения о последовательности ошибок, можно кратко просмотреть каждое событие ошибки. К важным полям, которые следует наблюдать, относятся fid_NtStatus, fid_UsbdStatus и fid_DebugText. Дополнительные сведения см. в разделе Основные сведения о событиях ошибок и кодах состояния. Чтобы отключить фильтр, нажмите кнопку Удалить в области Фильтр отображения .

Настраиваемые фильтры Netmon

Вы можете создать настраиваемые фильтры в Netmon. Самый простой способ — создать фильтр на основе данных на экране одним из следующих способов:

  • Щелкните правой кнопкой мыши поле в области Сведения о фрейме и выберите добавить выбранное значение в фильтр отображения.
  • Щелкните правой кнопкой мыши поле в области Сводка кадров и выберите Добавить [имя поля] в фильтр отображения.

Вы можете изменить операторы (например, OR, AND и ==) и значения фильтра, чтобы создать соответствующие выражения фильтра.

Основные сведения о событиях ошибок и кодах состояния

В нашем примере с неизвестным устройством большинство исключений USB-концентратора имеют fid_DebugText данные CreateDeviceFailure. Неясно, насколько серьезным является исключение, но текст отладки дает подсказку о причине: сбой операции, связанной с новым устройством. На данный момент предположим, что соседние события Create Device Failed являются избыточными. Последние два исключения: CreateDeviceFailure_Popup и GenErr_UserIoctlFailed. Всплывающее исключение звучит как ошибка, которая была предоставлена пользователю, но все эти ошибки могут быть связаны с неизвестной проблемой устройства.

События ошибок USB и другие события имеют значения состояния в своих данных, которые предоставляют ценную информацию о проблеме. Сведения о значениях состояния можно найти с помощью ресурсов, приведенных в следующей таблице.

Тип состояния Ресурс
fid_NtStatus См. раздел Значения NTSTATUS.
Поле состояния блока запросов USB (URB) или fid_UsbdStatus Найдите значение в виде USBD_STATUS в каталоге inc\api\usb.h в комплекте драйверов Windows (WDK). Можно также использовать USBD_STATUS. В этом разделе перечислены символьные имена и значения USBD_STATUS значений.

Чтение событий проблемы в обратном направлении

События, которые регистрируются перед событиями ошибки, могут дать важные подсказки о причине ошибки. Чтобы определить первопричину неизвестного устройства, следует просмотреть события, которые регистрируются перед ошибками. В этом примере начните смотреть назад с события CreateDeviceFailure_Popup, исключения от секунды к последнему. Выберите это событие, когда фильтр ошибок USB включен, а затем нажмите кнопку Удалить на панели Фильтр отображения . Фильтр ошибок USB по-прежнему отображается в области Фильтр отображения , и его можно будет применить позже. Но теперь фильтр отключен, и в области Сводка по кадрам отображаются все события, как показано на этом рисунке.

Microsoft Network Monitor.

Два события, которые регистрируются непосредственно перед событием CreateDeviceFailure_Popup, — это Dispatch и Complete of a USB control transfer. Поле fid_USBPORT_Device пути к порту равно нулю для обоих событий, что указывает на то, что целевой объект передачи является корневым концентратором. В fid_USBPORT_URB_CONTROL_TRANSFER структуре события завершения состояние равно нулю (USBD_STATUS_SUCCESS), что указывает на успешную передачу. Продолжайте изучать предыдущие события.

Следующие два предыдущих события — это четвертое (окончательное) событие Create Device Failed и четвертое (окончательное) исключение CreateDeviceFailure, которое мы рассмотрели ранее.

Следующее предыдущее событие — Endpoint Close. Это событие означает, что конечная точка больше не поддерживается. Данные события описывают устройство и конечную точку на этом устройстве. Путь к порту устройства — [1, 0, 0, 0, 0, 0]. Система, в которой мы запустили трассировку, имеет только контроллеры узлов (корневые концентраторы) и устройство, к которому мы подключались, поэтому этот путь к порту не описывает концентратор. Закрытая конечная точка должна находиться на одном подключенном устройстве, и теперь мы знаем, что путь устройства равен 1. Вполне вероятно, что драйверы сделали конечную точку устройства недоступной из-за проблемы, которая возникала ранее. Продолжайте изучать предыдущие события.

Следующее предыдущее событие — завершенная передача элементов управления USB. Данные события показывают, что целью передачи является устройство (путь к порту — 1). Структура fid_USBPORT_Endpoint_Descriptor указывает, что адрес конечной точки равен 0, поэтому это определяемая USB конечная точка управления по умолчанию. Состояние URB — 0xC0000004. Так как состояние не равно нулю, перенос, вероятно, не был успешным. Дополнительные сведения об этом USBD_STATUS значении см. в разделах usb.h и Understanding Error Events and Status Codes.

#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, устройство должно было ответить на этот запрос с помощью дескриптора устройства. Вместо этого устройство застопорит запрос, что привело к сбою перечисления. Таким образом, все четыре сбоя создания устройства были вызваны застопорившиеся запросы дескриптора устройства. Вы определили, что устройство неизвестно из-за сбоя перечисления и что перечисление завершилось сбоем, так как устройство не завершило запрос дескриптора устройства.