В зависимости от назначения, все usb устройства разделены по классам. Это деление довольно широкое и объединяет довольно большие группы устройств. Например, класс HID (human interface device) включает все устройства человеко-машинного взаимодействия (мышки, клавиатуры и тому подобное), класс Printer — все печатающие устройства и так далее. Зачем это деление нужно?
Дело в том, что для каждого класса устройств написаны свои спецификации, которые позволяют унифицировать общение с устройствами. Это удобно и разработчикам устройств (не надо каждый раз изобретать новые интерфейсы и протоколы) и производителям операционок (можно организовать поддержку всяких стандартных устройств на уровне операционок). Да и для простых пользователей навигация в менеджере устройств становится приятнее.
Наряду с классом, определить для чего предназначен девайс, как с ним общаться и какие дрова при этом использовать, помогает пара идентификаторов VID/PID, а также номер версии устройства.
VID — это уникальный идентификатор производителя (Vendor ID), а PID — это уникальный идентификатор продукта (Product ID). Каждый VID стоит денег и покупать его надо у некоммерческой международной организации, занимающейся разработкой USB, которая называется USB Implementers Forum или просто USB-IF. Покупая VID, производитель получает в своё распоряжение пачку PID-ов от 0x0000 до 0xFFFF и гарантии того, что серьёзные производители не будут делать свои продукты с такими же VID/PID (и писать под них свои дрова). То есть его оборудование будет идентифицироваться операционкой одназначно и она будет однозначно выбирать для работы с этим оборудованием нужные дрова.
Всю информацию о себе и отдельных своих частях (классы, VID/PID, интерфейсы, конечные точки …) устройства хранят в специальных структурах данных, называемых дескрипторами (от англ. description — описание).
Дескрипторы бывают стандартные и специфические. Стандартные дескрипторы для всех USB-устойств одинаковы, они обязательно есть в любом USB-устройстве и содержат общее описание устройства и его отдельных частей. Специфические дескрипторы содержат всякую специфическую для различных классов устройств информацию, соответственно, такие дескрипторы для каждого класса устройств свои.
Ниже описаны структуры и назначения различных стандартных дескрипторов:
Standard Device Descriptor (стандартный дескриптор устройства) — содержит информацию об устройстве вцелом и о количестве его возможных конфигураций. Такой дескриптор может быть в устройстве только один.
Структура стандартного дескриптора устройства | |||
Смещение (байт) |
Название поля | Размер (байт) |
Описание |
0 | bLength | 1 | Размер дескриптора в байтах (всегда 18) |
1 | bDescriptorType | 1 | Тип дескриптора (всегда 1) |
2 | bcdUSB | 2 | Номер версии USB в формате BCD |
4 | bDeviceClass | 1 | Код класса |
5 | bDeviceSubClass | 1 | Код подкласса (всегда 0) |
6 | bDeviceProtocol | 1 | Код протокола (всегда 0) |
7 | bMaxPacketSize0 | 1 | Максимальный размер пакета для нулевой конечной точки (64 для HS, 8 — для FS и LS) |
8 | idVendor | 2 | Идентификатор производителя |
10 | idProduct | 2 | Идентификатор продукта |
12 | bcdDevice | 2 | Номер версии устройства в формате BCD |
14 | iManufacturer | 1 | Индекс дескриптора строки, описывающей производителя |
15 | iProduct | 1 | Индекс дескриптора строки, описывающей продукт |
16 | iSerialNumber | 1 | Индекс дескриптора строки, содержащей серийный номер устройства |
17 | bNumConfigurations | 1 | Количество возможных конфигураций устройства |
Номер версии USB может принимать следующие значения:
- 0x0100 — USB1.0
- 0x0110 — USB1.1
- 0x0200 — USB2.0/li>
Коды классов бывают следующими:
- 0x00 — интерфейсы функционируют независимо друг от друга и каждый из них имеет собственный код класса.
- 0x01-0xFE — стандартные классы, поддерживающие различные спецификации для интерфейсов. Например, 01 — это аудиоустройство, 03 — HID, 07 — принтеры и так далее… Именно по коду класса комп первоначально определяет тип подключенного устройства, а уже потом анализирует другие данные.
- 0xFF — класс устройства определяется изготовителем./li>
Если устройство поддерживает режимы HS и FS, то у него должно быть два разных дескриптора для этих режимов, один из которых — это стандартный дескриптор устройства, а другой — уточняющий дескриптор устройства.
Device Qualifier Descriptor (уточняющий дескриптор устройства) — содержит дополнительную информацию об устройстве, для его работы на другой скорости.
Структура уточняющего дескриптора устройства | |||
Смещение (байт) |
Название поля | Размер (байт) |
Описание |
0 | bLength | 1 | Размер дескриптора в байтах |
1 | bDescriptorType | 1 | Тип дескриптора |
2 | bcdUSB | 2 | Номер версии USB в формате BCD |
4 | bDeviceClass | 1 | Код класса |
5 | bDeviceSubClass | 1 | Код подкласса |
6 | bDeviceProtocol | 1 | Код протокола |
7 | bMaxPacketSize0 | 1 | Максимальный размер пакета для нулевой конечной точки (64 для HS, 8 — для FS и LS) |
8 | bNumConfigurations | 1 | Количество дополнительных конфигураций устройства |
9 | bReserved | 1 | Зарезервировано (всегда 0) |
Standard Configuration Descriptor (стандартный дескриптор конфигурации) — содержит информацию об одной из возможных конфигураций устройства.
Структура стандартного дескриптора конфигурации | |||
Смещение (байт) |
Название поля | Размер (байт) |
Описание |
0 | bLength | 1 | Размер дескриптора в байтах |
1 | bDescriptorType | 1 | Тип дескриптора |
2 | wTotalLength | 2 | Общий объём данных (в байтах), возвращаемых для данной конфигурации |
4 | bNumInterfaces | 1 | Количество интерфейсов для данной конфигурации |
5 | bConfigurationValue | 1 | Идентификатор конфигурации (используется при запросе SetConfiguration для установки данной конфигурации) |
6 | iConfiguration | 1 | Индекс дескриптора строки, описывающей данную конфигурацию |
7 | bmAttributes | 1 | Характеристики конфигурации |
8 | MaxPower | 1 | Максимальный потребляемый ток, делённый на 2 |
Битовая маска атрибутов содержит следующую информацию:
- [7] — зарезервирован (должен равняться нулю)
- [6] — признак наличия у устройства собственного питания (0 — девайс питается от шины USB, 1 — девайс имеет собственный источник питания)
- [5] — возможность пробуждения по внешнему сигналу (0 — нет возможности, 1 — есть возможность)/li>
- [4:0] — зарезервированы (должны равняться нулю)/li>
Standard Interface Descriptor (стандартный дескриптор интерфейса) — содержит информацию об одном из доступных в какой-либо конфигурации интерфейсов.
Структура стандартного дескриптора интерфейса | |||
Смещение (байт) |
Название поля | Размер (байт) |
Описание |
0 | bLength | 1 | Размер дескриптора в байтах |
1 | bDescriptorType | 1 | Тип дескриптора |
2 | bInterfaceNumber | 1 | Номер интерфейса в наборе, поддерживаемом в данной конфигурации (нумерация начинается с нуля) |
3 | bAlternateSetting | 1 | Альтернативный номер интерфейса |
4 | bNumEndpoints | 1 | Количество конечных точек данного интерфейса (нулевая конечная точка не учитывается, поскольку она общая для всех) |
5 | bInterfaceClass | 1 | Код класса интерфейса |
6 | bInterfaceSubClass | 1 | Код подкласса интерфейса |
7 | bInterfaceProtocol | 1 | Код протокола |
8 | iInterface | 1 | Индекс дескриптора строки, содержащей описание данного интерфейса |
Standard Endpoint Descriptor (стандартный дескриптор конечной точки) — содержит информацию об одной из доступных для какого-либо интерфейса конечных точек.
Структура стандартного дескриптора конечной точки | |||
Смещение (байт) |
Название поля | Размер (байт) |
Описание |
0 | bLength | 1 | Размер дескриптора в байтах |
1 | bDescriptorType | 1 | Тип дескриптора |
2 | bEndpointAddress | 1 | Адрес конечной точки |
3 | bmAttributes | 1 | Атрибуты конечной точки |
4 | wMaxPacketSize | 2 | Максимальный размер пакета для конечной точки |
6 | bInterval | 1 | Интервал опроса конечной точки в миллисекундах (используется при передаче данных по прерываниям, для остальных, кроме изохронных, — игнорируется, для изохронных всегда равен 1) |
Битовая маска атрибутов содержит следующую информацию:
- [7:6] — зарезервированы (должны равняться нулю)
- [5:4] — тип использования конечной точки (00 — обычная, 01 — для явной обратной связи, 10 — для неявной обратной связи, 11 — зарезервировано)
- [3:2] — тип синхронизации (00 — нет синхронизации, 01 — асинхронная, 10 — адаптивная, 11 — синхронная), используется только для изохронных каналов/li>
- [1:0] — тип конечной точки (00 — канал сообщений, 01 — изохронный канал, 10 — канал передачи данных, 11 — канал прерываний)/li>
Unicode String Descriptor (дескриптор строки) — текст в формате Unicode. Строка не содержит нуль-терминатора, а её размер вычисляется как размер дескриптора минус два.
Структура стандартного дескриптора конечной точки | |||
Смещение (байт) |
Название поля | Размер (байт) |
Описание |
0 | bLength | 1 | Размер дескриптора в байтах |
1 | bDescriptorType | 1 | Тип дескриптора |
2 | bString | N | Строка в формате Unicode |
Дескрипторы строк являются необязательными. Если девайс не поддерживает дескрипторы строк, то во всех остальных дескрипторах индексы дескрипторов строк, содержащих текстовое описание, должны быть равны нулю.
При подключении USB-устройства, хост с помощью управляющих передач запрашивает у устройства список дескрипторов в следующем порядке:
- стандартный дескриптор устройства
- дескрипторы конфигураций
Причём при запросе дескриптора конфигурации хост получает сразу все дескрипторы (дескрипторы интерфейсов, конечных точек), относящиеся к этой конфигурации. Общий объём этих дескрипторов хосту заранее неизвестен, он хранится в поле wTotalLength дескриптора конфигурации, поэтому хост сначала запрашивает первые 8 байт этого дескриптора, запоминает из прочитанных данных значение поля wTotalLength, а потом снова запрашивает этот же дескриптор конфигурации, но размер запрашиваемых данных уже указывает равным wTotalLength. В результате такого трюка устройство присылает хосту все дескрипторы, относящиеся к данной конфигурации, в следующем виде:
- дескриптор конфигурации
- дескриптор интерфейса 1
- дескриптор конечной точки 1 для интерфейса 1
- дескриптор конечной точки 2 для интерфейса 1
- …
- дескриптор интерфейса 2
- дескриптор конечной точки 1 для интерфейса 2
- дескриптор конечной точки 2 для интерфейса 2
- …
- …
Специфические дескрипторы мы рассмотрим подробнее когда будем разрабатывать какой-нибудь конкретный девайс, какого-нибудь определённого класса, а пока на этом всё.
- Часть 1. Основы.
- Часть 2. Как происходит передача данных по шине.
- Часть 3. Что должно уметь любое USB-устройство.
- Часть 4. Дескрипторы и классы.
- Часть 5. Программная реализация low speed устройства USB. Схема.
- Часть 6. Программная реализация LS устройства USB. Физика и приём пакетов.
- Часть 7. Программная реализация LS устройства USB. Разбираем пакеты по типам.
- Часть 8. Программная реализация LS устройства USB. Передача по USB произвольного буфера и пакетов подтверждения.
- Часть 9. Программная реализация LS устройства USB. Продолжаем разбираться с принятыми пакетами.