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


Пример. Устранение неполадок неизвестного USB-устройства с помощью ETW и Netmon

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

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

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

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

Обычно, когда USB-драйверам не удается перечислить устройство, драйвер концентратора по-прежнему сообщает о подключении устройства к Windows, и USB-устройство помечается как неизвестное в Диспетчере устройств. Устройство имеет идентификатор устройства USB\VID_0000&PID_0000, а также идентификатор оборудования USB\UNKNOWN и совместимый идентификатор 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 на следующей странице показано первое несводное событие в данном примере трассировки.

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

Cнимок экрана с интересующим устройством, выбранным в

Описание событий и нагрузка данных

В примере журнала первым событием после сводных событий устройства является завершение ожидания ИРП на пробуждение концентратором USB. Мы подключили устройство, и контроллер узла или концентратор активируется в ответ. Чтобы определить, какой компонент просыпается, просмотрите данные события. Данные отображаются в области сведений о кадре, которая отображается в структуре дерева примерно в следующей форме:

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 Wait Wake USB Hub, и вы увидите структуру ETW с именем fid_USBHUB_Hub. Имя структуры имеет следующие компоненты:

Срок Описание
fid_ Типичный префикс для структуры USB ETW.
USBHUB_ Указывает, что драйвер USB-концентратора зарегистрировал событие.
Остальная часть строки Имя объекта, описываемого данными структуры. Для этого события это объект Hub.

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

Сетевой монитор Microsoft — детали кадра.

Структура концентратора очень похожа на две другие структуры, которые обычно отображаются в событиях USB ETW: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. Неясно, насколько серьезным является исключение, но отладочный текст указывает на причину: операция, связанная с новым устройством, завершилась ошибкой. Предположим пока, что смежные события создания устройства являются избыточными. Последние два исключения: 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 по-прежнему отображается в области фильтра отображения , и его можно повторно применить позже. Но теперь фильтр отключен, а панель "Сводка кадров " отображает все события, как показано на этом рисунке.

сетевой монитор Майкрософт.

Два события, которые регистрируются непосредственно перед событием CreateDeviceFailure_Popup, — это регистрация "Dispatch" и "Complete" передачи управления USB. Поле пути к порту 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 и ознакомьтесь с описанием событий ошибок и кодов состояния.

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