Отладка составных USB-устройств: номера интерфейсов, IAD, конечные точки и привязка драйверов

Как отлаживать составные USB-устройства, когда один интерфейс работает, другой падает, или хост привязывает неверный драйвер.

USB, составное устройство, IAD, интерфейс, привязка драйвера, composite

Составные USB-устройства удобны и опасны. Одно физическое устройство может выставить HID-управление, CDC serial, mass storage, вендорные конечные точки, аудио, видео или диагностические интерфейсы. Когда всё описано корректно, хост привязывает правильные драйверы, и каждая функция работает. Когда одно поле дескриптора неверно, всё устройство может выглядеть ненадёжным.

Запросы вроде «USB composite device not recognized», «CDC interface not showing», «HID works but serial does not», «wrong driver binding USB interface» обычно указывают на структуру дескриптора, нумерацию интерфейсов, назначение конечных точек или поведение Interface Association Descriptor.

Составные устройства требуют связной конфигурации

Configuration descriptor — это верхнеуровневая карта. Он должен описывать полную длину, число интерфейсов, характеристики питания и все вложенные interface и endpoint дескрипторы. Если wTotalLength неверный, хост может не прочитать все функции. Если число интерфейсов неверно, хост может проигнорировать последующие. Если адреса конечных точек сталкиваются, передачи становятся двусмысленными или невалидными.

Изучите:

  • полную длину конфигурации
  • число интерфейсов
  • номера интерфейсов
  • alternate settings
  • адреса конечных точек
  • направления конечных точек
  • значения class, subclass, protocol
  • порядок дескрипторов

Захват должен показать, запросил ли хост полную конфигурацию и какие байты вернуло устройство.

IAD помогает группировать связанные интерфейсы

Interface Association Descriptors часто используются, чтобы сгруппировать несколько интерфейсов, принадлежащих одной функции, например CDC communication + CDC data. Без корректной группировки хост может привязать драйверы некорректно или выставить только часть функции.

Что изучать в IAD:

  • номер первого интерфейса
  • число интерфейсов
  • function class, subclass, protocol
  • размещение перед группируемыми интерфейсами
  • согласованность с реальными interface descriptor'ами

Если CDC serial не появляется, а HID работает — HID-интерфейс может быть в порядке, а группировка CDC — нет.

Коллизии адресов конечных точек легко пропустить

Адреса конечных точек включают направление. Endpoint 0x81 и 0x01 — разные направления, но две IN-конечные точки с одинаковым адресом в одной конфигурации устройства невалидны. Команды прошивок иногда копируют endpoint дескрипторы между интерфейсами и забывают обновить адреса.

Симптомы:

  • один интерфейс работает, другой молчит
  • хост шлёт передачи на неожиданную конечную точку
  • класс-драйвер загружается, но приложение не получает данные
  • STALL или тайм-аут конечной точки после конфигурации
  • только одна функция работает одновременно

Захват должен показать endpoint descriptors и последующий трафик передач бок о бок.

Привязка драйверов — тоже доказательство

Хост выбирает драйверы на основе дескрипторов. Устройство, которое привязалось неверно, может иметь дескрипторные доказательства, объясняющие почему. Class, subclass, protocol, interface association, compatible IDs и OS-специфичные дескрипторы могут влиять на привязку.

Не диагностируйте привязку драйвера только по Диспетчеру устройств или логам приложения. Сравните класс-управляющие запросы хоста с деревом дескрипторов. Если ожидаемые класс-запросы не пришли, хост, скорее всего, не привязал ожидаемый драйвер.

Место Bus Scope

Bus Scope помогает командам прошивок изучать составные устройства на двух уровнях:

  • карта дескрипторов
  • доказательства передач после привязки драйвера

Хороший .bscope-сеанс по отладке составного устройства показывает:

  • все интерфейсы
  • IAD-группировку
  • назначения конечных точек
  • класс-управляющие запросы на интерфейс
  • сырые байты дескрипторов
  • статус передач после конфигурации

Это делает разговор поддержки конкретным. Вместо «Windows не любит наше составное устройство» отчёт может сказать «интерфейс 2 не получает CDC класс-запросы, потому что grouping descriptor не совпадает с заявленной раскладкой».

Это и есть уровень доказательств, нужный командам прошивок.