На склад поступили жидко-кристаллические индикаторы и дисплеи от KSE
РадиоЛоцман - Все об электронике

Популярно о USB. Часть 2

Часть 1

Немоляев А. В, г. Екатеринбург

Дескрипторы

Технология правильного хранения аккумуляторов и батареек по рекомендациям FANSO и EVE Energy

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

  • дескриптор устройства,
  • дескриптор конфигурации,
  • дескриптор интерфейса,
  • дескриптор конечной точки.

Все эти виды дескрипторов должны обязательно присутствовать в USB-устройстве. Рисунок 2 поясняет сказанное.

 
Рисунок 2.

Конечные точки объединяются в интерфейс. Каждому интерфейсу соответствует драйвер операционной системы (ОС) хоста. Некоторые устройства могут иметь несколько интерфейсов, которые могут функционировать одновременно. Телефонный аппарат VOIP может иметь интерфейс клавиатуры и аудио интерфейс, тогда ОС хоста будет использовать 2 различных драйвера для каждого интерфейса. А прикладная программа будет взаимодействовать с этими драйверами для функционирования. Несколько интерфейсов могут объединяться в конфигурацию. У USB-устройства может быть несколько конфигураций, но не могут быть активными несколько конфигураций одновременно, необходимо переключение между конфигурациями. В наших примерах USB-устройства с несколькими дескрипторами конфигураций и несколькими дескрипторами интерфейсов мы не использовать будем.

Кроме базовых дескрипторов, которые являются основными, для создания работоспособного USB-устройства, имеются и прочие дескрипторы. Об этих дескрипторах расскажем позднее.

Что представляют собой дескрипторы мыши USB, можно увидеть, воспользовавшись утилитой lsusb. Эта команда не в точности выдает структуру дескрипторов USB-устройства, но очень близкую. Введем команду и перенаправим ее вывод в текстовый файл, а затем файл откроем в любом текстовом редакторе

  alex@big:~$  sudo  lsusb  -d  0458:003a   -v  >  dsc.txt

Здесь в качестве параметра указан идентификатор устройства, дескрипторы которого требуется вывести, а также дополнительные ключи. Ищем и открываем файл dsc.txt. Как узнать идентификатор мыши PC, говорилось выше.

Посмотрим на содержимое файла dsc.txt. Легко распознать секции с дескрипторами устройства, конфигурации, интерфейса и конечной точки. В названиях полей дескрипторов имеются префиксы, соответствующие типам данных:

Bus 003 Device 002: ID 0458:003a KYE Systems Corp. (Mouse Systems)
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0458 KYE Systems Corp. (Mouse Systems)
idProduct 0x003a
bcdDevice 1.00
iManufacturer 1 Genius
iProduct 2 Optical Mouse
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 4 HID-compliant MOUSE
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 2 Mouse
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 62
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0004 1x 4 bytes
bInterval 10
Device Status: 0x0000
(Bus Powered)

Начнем с описания полей дескриптора устройства:

Поле
Размер
Описание
bLength
1
размер дескриптора в байтах
bDescriptorType
1
тип дескриптора
bcdUSB
2
номер спецификации USB, которой удовлетворяет устройство (в двоично-десятичном формате)
bMaxPacketSize
1
максимальный размер пакета для конечной точки 0, из ряда 8, 16, 32, 64
idVendor
2
код разработчика
idProduct
2
код разработки
bcdDevice
2
код версии разработки (в двоично-десятичном формате)
iManufacturer
1
индекс текстовой строки производителя
iProduct
1
индекс текстовой строки изделия
iSerial
1
индекс текстовой строки серийного номера
bNumConfigurations
1
количество возможных конфигураций

Поле bMaxPacketSize задает размер максимального пакета конечной точки управления. Конечная точка управления используется для приема команд от хоста. Эта точка не имеет дескриптора, задается только размер ее буфера. Дескрипторы могут содержать не только информацию в двоичном коде, а так же и текст. Эта информация необязательна для работы USB-устройства, но весьма ценна для человеческого восприятия. Для передачи этой информации служат строковые дескрипторы. Дескриптор строки состоит из 2-байтных символов UNICODE-16 v1. Такая же кодировка используется в Windows. Структура строковых дескрипторов в дампе вывода не описана, lsusb извлекла текст по умолчанию и подставила в нужные места отчета. Поля с индексами указывают на номер строкового дескриптора в пуле строковых дескрипторов. Если в индексном поле задан 0, то считается, что строковый дескриптор не задан. Из дампа информации, выведенной lsusb, видно, что iSerial не задано, а описатель iProduct имеет индекс 2.

Поля bDeviceClass, bDeviceSubClass и bDeviceProtocol используются в USB устройствах, относящихся к стандартизованным классам. Ранее уже сообщалось о существовании унифицированных классов устройств, существующих в рамках стандарта USB. Классы устройств – это надстройка над базовым USB. По аналогии, протокол прикладного уровня HTTP – это надстройка над TCP/IP. Рассматриваемая мышь относится к классу устройств HID. Но это отдельная большая тема. Важно знать, что совсем необязательно разбираться в протоколах типа HID, для того чтобы создавать устройства на микроконтроллерах с USB.

Далее идет дескриптор конфигурации:

Поле
Размер
Описание
wTotalLength
1
полная длина возвращаемых данных
bNumInterfaces
1
количество интерфейсов
bConfigurationValue
1
условный номер конфигурации
iConfiguration
1
индекс строкового дескриптора к конфигурации
bmAttributes
1
атрибуты конфигурации
bMaxPower
1
максимальный ток потребления в единицах по 2 мА

Поле bMaxPower задает максимальный ток, потребляемый USB-устройством. Задается в единицах, кратных 2 мА. В дампе lsusb этот параметр уже переведен в миллиамперы. Поле bmAttributes – набор битов, способ одним байтом задать несколько параметров. Этим полем задаются энергетические характеристики устройства. Поэтому сделаем некоторое введение.

Все USB-устройства делятся на 3 класса по потребляемой энергии: питаемые от шины, питаемые от шины с высоким потреблением энергии и имеющие собственный источник энергии. Напомним, что USB-устройства, подключаемые к шине USB, могут получать энергию по самой шине. Те что потребляют меньше 100 миллиампер, относятся к классу с низким потреблением (Low power ). А USB-устройства потребляющие до 500 миллиампер от самой шины, относятся к мощным (High power). Третья категория – это те, что имеют собственный источник (Self powered). Имеющие собственный источник питания могут потреблять дополнительно и от шины, но не боле 100 миллиампер.

Если установлен бит 6 поля bmAttribute, то это указывает, что USB-устройство имеет собственный источник питания. Бит 5 – что USB-устройство может являться источником сигнала пробуждения, выводящим вышестоящий хаб из состояния низкого потребления. Теперь ясно, почему моя мышь может разбудить компьютер. Остальные биты зарезервированы.

В дескрипторе интерфейса интересными пока являются только поля bNumEndpoints и поле iInterface. Из названия ясно, что одно поле задает количество конечных точек в интерфейсе, не считая управляющей конечной точки. Другое поле – индекс строкового дескриптора, поясняющий интерфейс. Поля, относящиеся к секции HID Device Descriptor, рассматривать не будем.

Последним идет дескриптор единственной конечной точки:

Поле
Размер
Описание
bEndpointAddress
1
адрес конечной точки
bmAttributes
1
битовое поле атрибутов
wMaxPacketSize
1
максимальный размер пакета
bInterval
1
интервал опроса в миллисекундах

Адрес конечной точки состоит из 2-х частей: номера и направления. Для номера выделены биты 0..3, а для направления предназначен бит 7. Если этот бит установлен, то конечной будет точка ввода. Остальные биты зарезервированы. Всего можно адресовать до 30 точек – 15 на ввод и 15 на вывод. Нулевой адрес зарезервирован для точки управления. Для мыши видно, что конечная точка типа ввода посылает данные на хост и имеет номер 1.

Поле bmAttributes, биты 0..1 задают тип точки: 0 – управления, 1 – изохронной передачи, 2 – массовой передачи, 3 – передачи по прерыванию. Биты 2..5 имеют смысл только для изохронных типов конечных точек. Биты 2..3 задают тип синхронизации для изохронной конечной точки: 0 – нет синхронизации, 1 – асинхронная, 2 – адаптивная, 3 – синхронная. Биты 4..5 задают способ использования изохронной конечной точки: 0 – для данных, 1 – обратная связь, 2 – данные с предоставлением неявной обратной связи, 3 – зарезервировано. Смысл этих параметров относится к изохронным передачам, которые не будем рассматривать подробно. Поле wMaxPacketSize задает максимальный размер пакета, который способна принять точка. Мышь передает хосту пакеты данных по 4 байта. Поле bInterval задает максимально возможную задержку опроса для конечных точек передач по прерыванию. При поступлении запроса от хоста на передачу данных данные будут переданы с возможной задержкой не более, чем значение в bInterval. Для изохронных точек всегда 1. Для остальных не имеет значения. Мышь опрашивается с периодичностью 10 мс.

Первая программа

Напишем приложение, работающее с USB-устройством. В качестве устройства будем использовать мышь USB. Программа написана на GCС в Linux. Для навигации по исходному коду программы и библиотек лучше использовать какую-нибудь IDE для C.

Проблема написания приложения для устройства USB состоит в необходимости создания драйвера. Создание драйвера – задача не рядовая. Получается, что для изучения USB требуется предварительно научиться писать драйверы для ОС.

Другой подход – это использовать имеющиеся драйверы ОС. Уже говорилось о USB-устройствах, имеющих архитектуру, относящуюся к определенным стандартизованным классам. Для таких типов устройств уже имеются драйверы. Например, мышь относится к классу HID, и для нее имеются стандартные драйверы в ОС. Такой подход имеет право на жизнь. Через API из своей программы обращаетесь к ОС, а она через драйвер к USB-устройству. Но тогда созданное USB-устройство должно поддерживать протокол HID. Это достаточно сложная надстройка над базовой функциональностью USB.

Оба этих метода не подходят для начинающих изучать USB. Так как быть? К счастью для новичков, имеется библиотека libusb. Первоначально она создавалась для Linux, теперь имеются порты и для Windows. Уже известная утилита lsusb использует библиотеку libusb. Эта библиотека позволяет писать прикладные программы, напрямую обращающиеся к USB-устройству, устраняя необходимость использования драйверов ОС.

В Ubuntu для программирования требуется установить пакет libusb-dev, или установить библиотеку из исходных кодов. Для понимания работы с библиотекой необходимо знание работы со структурами и со списками из структур на языке C. Для компилирования так же необходимо иметь на машине компилятор GCC. На моем компьютере была установлена версия библиотеки libusb 0.1.12.

Утилитой lsusb посмотрите коды производителя и продукта своей мыши. Распакуйте архив host_mouse.tar.gz в любой доступный каталог. Откройте файл c любым редактором, измените эти коды на коды своей мыши в тексте программы. Из командной строки зайдите в каталог с makefile и выполните команду make all. Запуск компилированной программы осуществлять с правами суперпользователя.

Функции usb_find_busses и usb_find_devices находят все шины хоста и все устройства на шинах и сохраняют эти сведения во внутренних структурах данных. Строение этих структур можно изучить по исходным текстам библиотеки. Функция usb_get_busses возвращает ссылку на глобальную структуру, где хранятся сведения о шинах, устройствах на шинах и дескрипторах этих устройств. Представленная программа находит подключенное к хосту устройство по кодам производителя и продукта. Поиск ведется в двух циклах. Во внешнем цикле проходятся шины, а во внутреннем выполняется проход по устройствам, подключенным к шине. Найденное устройство открывается, и отключается драйвер операционной системы. Мышь относится к классу HID, и ОС автоматически подключает нужные драйверы для работы во время энумерации. После отключения драйвера мышь перестанет работать с ОС, и приложение может использовать мышь монопольно. Для возобновления работы мыши с OC нужно извлечь мышь из системного блока, а затем вставить. Это приведет к процессу энумерации и подключению драйверов. Можно сбросить мышь программно функцией usb_reset(). После отключения драйвера программа выводит на экран строковые дескрипторы, на которые указывают поля iManufacturer, iProduct и iConfiguration. Найти описание этих полей помогут файлы usb.h и usb.c, там имеется описание структурного типа usb_device_descriptor. Значения этих полей определяются по содержимому структуры descriptor для найденного устройства.

Часть 3

Электронные компоненты. Бесплатная доставка по России
Для комментирования материалов с сайта и получения полного доступа к нашему форуму Вам необходимо зарегистрироваться.
Имя