Отладка USB-дескрипторов для HID- и CDC-устройств
Как команды разработки прошивок могут диагностировать HID- и CDC-устройства, изучая доказательства в дескрипторах и передачах, а не догадываясь по ошибкам драйвера.
HID- и CDC-устройства популярны, потому что они позволяют командам прошивок поставлять полезные USB-интерфейсы без написания собственного драйвера для каждого хоста. Это удобство зависит от точности дескрипторов. Когда ломается HID-клавиатура, датчик, serial-мост или составное устройство, корень проблемы часто виден в данных дескрипторов раньше, чем проявляется в приложении.
Отладка дескрипторов — дело не самое эффектное, но один из самых быстрых способов закрыть кейс поддержки USB.
HID: report descriptor — это контракт
Для HID-устройств хосту нужна информация шире, чем просто данные о конечной точке. Нужен HID report descriptor. Этот дескриптор задаёт report IDs, usages, размеры, количества, логические диапазоны и то, как интерпретировать байты.
Частые ошибки в HID:
- длина репорта не совпадает с реальной полезной нагрузкой interrupt-передач
- report ID используется в прошивке, но не объявлен последовательно
- logical min и max не соответствуют представлению данных
- usage page или usage не совпадают с ожиданиями хоста
- endpoint interval нереалистичен для поведения устройства
- предположения о boot-протоколе конфликтуют с поведением report-протокола
Ошибка со стороны хоста может выглядеть размыто. Захват, в котором видны байты дескрипторов и interrupt-передачи, делает расхождение очевидным.
CDC: важна планировка интерфейсов
Устройства CDC ACM обычно выставляют коммуникационный интерфейс и интерфейс данных. Хост ожидает связный набор дескрипторов и классовых запросов. Пропущенный функциональный дескриптор, неверная interface association или несовпадение конечных точек могут помешать появлению виртуального COM-порта.
Что изучать:
- класс и подкласс интерфейса
- дескрипторы CDC header, ACM, union и call management
- notification-конечная точка
- bulk IN и OUT конечные точки
SET_LINE_CODINGSET_CONTROL_LINE_STATE- передачи данных после конфигурации
Если serial-порт появляется, но байты не идут, проблема может быть в поведении конечных точек или в протоколе приложения. Если serial-порт вовсе не появляется, первым делом смотрите дескрипторы и классовые запросы.
Составные устройства требуют дополнительной дисциплины
Составные устройства могут сочетать HID, CDC, mass storage, вендорные интерфейсы и многое другое. Это удобно, но умножает возможные сбои. Ошибка в дескрипторе одного интерфейса может повлиять на привязку драйвера для всего устройства.
Для отладки составных устройств изучите:
- полную длину конфигурации
- номера интерфейсов
- interface association descriptors
- уникальность конечных точек
- размещение классовых дескрипторов
- запросы хоста по интерфейсам
Не считайте, что «прошивка шлёт правильные байты», пока захват не докажет, что хост увидел правильную структуру.
Почему важны и сырые байты, и классовая интерпретация
Сырые байты — это правда. Классовая интерпретация делает их применимыми. Хороший инструмент диагностики USB должен показывать и то, и другое. Инженеру нужно видеть точные байты дескриптора, когда что-то не так, но также нужны декодированные поля, чтобы не считать смещения вручную в каждом кейсе.
Лучший рабочий процесс:
- изучить декодированное дерево дескрипторов
- перейти к сырым байтам по подозрительным полям
- сравнить запросы хоста с ответами прошивки
- изучить передачи по конечным точкам после конфигурации
- сохранить сеанс для воспроизведения или передачи в поддержку
Такой процесс держит диагноз привязанным к доказательствам.
Место Bus Scope
Bus Scope создан для команд прошивок, аппаратных лабораторий и вендоров устройств, которым нужен повторяемый ответ на вопрос «почему сломался USB-трафик». Он держит в одном рабочем месте контекст device explorer, детали пакета, сырые байты, дескрипторы, классовые наблюдения, фильтры и сохранённые .bscope-сеансы.
Для кейсов HID и CDC Bus Scope помогает отвечать на вопросы:
- завершилось ли перечисление?
- совпали ли дескрипторы с целевым классом?
- послал ли хост ожидаемые классовые запросы?
- совпали ли передачи по конечным точкам с ожиданиями по репортам или line coding?
- это проблема прошивки, драйвера хоста или протокола приложения?
Это и есть разница между «driver failed» и пониманием того, какой USB-контракт нарушен.