Interested Article - USB core
![](/images/005/328/5328669/1.jpg?rand=948717)
![](https://cdn.wafarin.com/avatars/99c307a7bcd9067efb2967906eef4b87.jpg)
- 2020-09-08
- 1
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 для устранения прочих видов буферных ограничений .
Примечания
- 18 мая 2009 года. (англ.)
- 19 мая 2009 года. (англ.)
- ↑ 1 мая 2010 года. (англ.)
Ссылки
- (англ.)
- (англ.)
![](https://cdn.wafarin.com/avatars/99c307a7bcd9067efb2967906eef4b87.jpg)
- 2020-09-08
- 1