Interested Article - USB core

USB Core — это подсистема ядра Linux , созданная для поддержки USB -устройств и контроллеров шины USB. Цель её создания — абстрагирование от аппаратной реализации стандарта USB (либо аппаратно-зависимых функций) путём определения набора структур данных, макросов и функций.

История развития

Поддержка USB в ядро Linux была добавлена вскоре после появления ветки ядра 2.2 и незадолго до начала работ в линейке 2.3. Разработки из линейки 2.3 регулярно переносились в линейку 2.2, добавляя тем самым новые возможности, как например, поддержку «горячего подключения», новые драйверы, оптимизацию работы. Линейка ядра 2.5 унаследовала все эти улучшения, причём к ним добавилась поддержка работы с USB 2.0 и, как следствие, более высокая производительность, более устойчивая работа между устройствами, упрощение прикладного интерфейса (делать ошибки в коде стало труднее), а также ведение внутренней документации.

Поскольку возможность запуска Linux со временем появилась и на многих медиаустройствах, то в ходе своей эволюции поддержка USB в Linux разделилась на две части. С одной стороны, Linux может запускаться с подключаемых к устройству USB-устройств (например, флэш-накопители), с другой стороны, на основном компьютере, к которому подключают USB-устройства, также может работать Linux. Используемые при этом драйверы USB сильно различаются, поэтому чтобы их различать для драйверов устройств было введено соответствующее название англ. gadget drivers .

Принцип работы

Внутри ядра драйверы основной ОС обращаются к прикладным интерфейсам USB Core. Существует два типа публичных прикладных интерфейса USB Core, нацеленных на два различных уровня драйвера USB: драйверы общего назначения , доступные через фреймворки драйвера, как, например, блочное, символьное или сетевое устройства, и драйверы, являющиеся частью ядра , участвующие в управлении шиной USB. Такие драйверы ядра включают в себя драйвер хаба, управляющего деревом USB-устройств, а также несколько различных типов драйверов хост-контроллера ( англ. host controller driver , сокр. HCD), который контролирует отдельные шины.

Метод определения оптимального способа работы драйверов с USB-устройством довольно сложный:

  • USB поддерживает 4 способа передачи данных (control, bulk, interrupt и isochronous). Два типа из них (control и bulk) используют всю доступную пропускную способность, тогда как остальные два (interrupt и isochronous) должны обеспечивать заданную пропускную способность.
  • Модель описания устройства включает в себя одну или более «конфигураций» для каждого устройства, причём активной в любой момент времени может быть только одна из них. Устройства стандарта «high speed» должны поддерживать и конфигурации для работы со стандартом «full speed», а также возможна поддержка конфигураций и для других стандартов/скоростей.
  • Конфигурации имеют один или более «интерфейсов», каждый из которых может содержать различные параметры/настройки. Такие интерфейсы могут соответствовать стандарту USB, а могут быть специфичными лишь для определенного производителя/устройства. И именно к интерфейсам и привязаны драйверы USB-устройств, а не к устройству непосредственно.
  • Интерфейсы имеют одну или более «конечных точек» (endpoints), каждая из которых поддерживает один тип и направление передачи данных (например, «bulk out» или «interrupt in»). Полная конфигурация может иметь до шестнадцати конечных точек в каждом направлении.
  • Передача данных по USB осуществляется пакетами, причём каждая точка имеет запись о максимальном размере пакета.
  • Прикладной интерфейс USB в Linux поддерживает синхронные вызовы для передачи сообщений типа control и bulk. Также поддерживаются асинхронные вызовы для всех видов передачи данных путём использования специальных структур запроса, называемых «блоками запроса USB» ( англ. USB Request Blocks , сокр. URBs).

Единственные драйверы хостовой ОС, которые реально обращаются к устройству (регистры чтения/записи, обработка сигналов прерываний и т. д.), это драйверы хост-контроллера. В теории все драйверы хост-контроллера поддерживают схожий функционал за счет использования единого прикладного интерфейса. На практике же это начало поддерживаться лишь в версии ядра 2.5, но при этом есть различия в обработке ошибок .

Список стандартных прикладных интерфейсов

Ниже перечислены стандартные прикладные интерфейсы программирования (API), входящие в состав USB Core .

Название Функции
usb_init_urb Инициализирует URB для их последующего использования драйвером USB
usb_alloc_urb Создает новый URB для его последующего использования драйвером USB
usb_free_urb Освобождает память, занимаемую URB, по окончании работы всех пользователей с ним
usb_get_urb Увеличивает счетчик ссылок на URB
usb_submit_urb Посылает запрос асинхронной передачи к конечному устройству
usb_unlink_urb Прерывает/отменяет запрос передачи к конечному устройству
usb_kill_urb Отменяет запрос передачи и ожидает его завершения
usb_control_msg Создает сообщение управления URB, отсылает его и ожидает выполнения
usb_bulk_msg Создает общее сообщение URB, отсылает его и ожидает выполнения
usb_sg_init Инициализирует запрос ввода-вывода общего типа или прерывания на базе распределённого списка
usb_sg_wait Синхронно выполняет запрос разделения/объединения
usb_sg_cancel Останавливает разделение/объединение ввода-вывода, начатого по команде usb_sg_wait
usb_get_descriptor Отправляет обобщённый запрос получения дескриптора (GET_DESCRIPTOR)
usb_string Возвращает строковый дескриптор в формате ISO 8859-1
usb_get_status Отправляет вызов GET_STATUS
usb_clear_halt Сообщает устройству о сбросе состояния ожидания для конечного устройства
usb_set_interface Делает активными альтернативный набор настроек
usb_reset_configuration Программная перезагрузка устройства
usb_register_dev Регистрирует USB-устройство и запрашивает младший номер
usb_deregister_dev Разрегистрирует динамический младший номер USB-устройства
usb_match_id Находит первый совпавший usb_device_id для устройства или интерфейса
usb_register_driver Регистрирует USB-драйвер
usb_deregister Разрегистрирует USB-драйвер
usb_ifnum_to_if Получает объект интерфейса для данного номера интерфейса
usb_altnum_to_altsetting Получает структуру альтернативных настроек для данного номера интерфейса
usb_driver_claim_interface Привязывает драйвер к интерфейсу
usb_driver_release_interface Отвязывает драйвер от интерфейса
usb_find_interface Находит указатель usb_interface для драйвера и устройства
usb_get_dev Увеличивает счетчик ссылок структуры USB-устройства
usb_put_dev Освобождает используемую структуру USB-устройства
usb_get_intf Увеличивает счетчик ссылок структуры интерфейса USB
usb_put_intf Освобождает используемую структуру интерфейса USB
usb_lock_device_for_reset Корректно накладывает блокировку на устройство для последующей перезагрузки
usb_find_device Находит требуемое USB-устройство в системе
usb_get_current_frame_number Возвращает номер текущего кадра шины
usb_buffer_alloc Выделяет DMA-совместимый буфер для размещения URB_NO_xxx_DMA_MAP
usb_buffer_free Освобождает память, выделенную при помощи usb_buffer_alloc
usb_buffer_map Создает DMA-привязки к URB
usb_buffer_dmasync Синхронизирует просмотр буферов DMA и центрального процессора
usb_buffer_unmap Разрушает DMA-привязки к URB
usb_buffer_map_sg Создает распределённые DMA-привязки к конечным точкам
usb_buffer_dmasync_sg Синхронизирует просмотр распределённых буферов DMA и центрального процессора
usb_buffer_unmap_sg Разрушает распределённые DMA-привязки
usb_hub_tt_clear_buffer Сбрасывает режим control/bulk в высокоскоростном хабе
usb_root_hub_lost_power Вызывается HCD в случае потери корневым хабом питания по Vbus-шине
usb_reset_device Выполняет перезагрузку порта USB для переинициализации устройства

Модели USB API

Существуют две основные модели ввода-вывода в USB API. Наиболее простая модель является асинхронной: драйверы отправляют запрос в виде URB, а затем обратный вызов URB на следующем шаге завершает операцию. Все типы передачи USB поддерживают данную модель, однако существуют специальные модели для управляющих URB (которые всегда имеют собственные настройки и статусы, но не всегда обладают возможностью продвижения данных ( англ. data stage ) и изохронных URB (которые допускают передачу больших пакетов и включают в себя генерацию отчетов по каждому некорректному пакету). Такие модели строятся на основе поддержки синхронного API, в котором драйвер вызывает подпрограмму, которая размещает в памяти один или более URB, отправляет их и ждет их завершения. Также существуют синхронные обертки для однобуферных управляющих и массовых передач (которые неудобны для применения в некоторых сценариях драйверного отключения), а также для потоковой передачи на основе распределённых списков (потоком или с прерываниями).

Драйверам USB требуется наличие буферов, которые могут быть использованы для прямого доступа к памяти (DMA), хотя им не обязательно самостоятельно выполнять привязку DMA. Существуют API, применяемые при выделении DMA-буферов, поскольку они смогут предотвратить использование некорректных буферов на некоторых системах. В некоторых случаях драйверы могут использовать 64-битный режим DMA для устранения прочих видов буферных ограничений .

Примечания

  1. 18 мая 2009 года. (англ.)
  2. 19 мая 2009 года. (англ.)
  3. 1 мая 2010 года. (англ.)

Ссылки

  • (англ.)
  • (англ.)
Источник —

Same as USB core