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 сильно различаются, поэтому чтобы их различать для драйверов устройств было введено соответствующее название Introduction to USB on Linux .
Принцип работы Внутри ядра драйверы основной ОС обращаются к прикладным интерфейсам USB Core. Существует два типа публичных прикладных интерфейса USB Core, нацеленных на два различных уровня драйвера USB: драйверы общего назначения, доступные через фреймворки драйвера, как, например, блочное, символьное или сетевое устройства, и драйверы, являющиеся частью ядра, участвующие в управлении шиной USB. Такие драйверы ядра включают в себя драйвер хаба, управляющего деревом USB-устройств, а также несколько различных типов драйверов хост-контроллера (, сокр. 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» (, сокр. URBs).
Единственные драйверы хостовой ОС, которые реально обращаются к устройству (регистры чтения/записи, обработка сигналов прерываний и т. д.), это драйверы хост-контроллера. В теории все драйверы хост-контроллера поддерживают схожий функционал за счет использования единого прикладного интерфейса. На практике же это начало поддерживаться лишь в версии ядра 2.5, но при этом есть различия в обработке ошибокUSB Host-Side API Model .
Список стандартных прикладных интерфейсов Ниже перечислены стандартные прикладные интерфейсы программирования (API), входящие в состав USB CoreUSB Core APIs .
Название Функцииusb_init_urb Инициализирует URB для их последующего использования драйвером USBusb_alloc_urb Создает новый URB для его последующего использования драйвером USBusb_free_urb Освобождает память, занимаемую URB, по окончании работы всех пользователей с нимusb_get_urb Увеличивает счетчик ссылок на URBusb_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_waitusb_get_descriptor Отправляет обобщённый запрос получения дескриптора (GET_DESCRIPTOR)usb_string Возвращает строковый дескриптор в формате ISO 8859-1usb_get_status Отправляет вызов GET_STATUSusb_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 Увеличивает счетчик ссылок структуры интерфейса USBusb_put_intf Освобождает используемую структуру интерфейса USBusb_lock_device_for_reset Корректно накладывает блокировку на устройство для последующей перезагрузкиusb_find_device Находит требуемое USB-устройство в системеusb_get_current_frame_number Возвращает номер текущего кадра шиныusb_buffer_alloc Выделяет DMA-совместимый буфер для размещения URB_NO_xxx_DMA_MAPusb_buffer_free Освобождает память, выделенную при помощи usb_buffer_allocusb_buffer_map Создает DMA-привязки к URBusb_buffer_dmasync Синхронизирует просмотр буферов DMA и центрального процессораusb_buffer_unmap Разрушает DMA-привязки к URBusb_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 (которые всегда имеют собственные настройки и статусы, но не всегда обладают возможностью продвижения данных () и изохронных URB (которые допускают передачу больших пакетов и включают в себя генерацию отчетов по каждому некорректному пакету). Такие модели строятся на основе поддержки синхронного API, в котором драйвер вызывает подпрограмму, которая размещает в памяти один или более URB, отправляет их и ждет их завершения. Также существуют синхронные обертки для однобуферных управляющих и массовых передач (которые неудобны для применения в некоторых сценариях драйверного отключения), а также для потоковой передачи на основе распределённых списков (потоком или с прерываниями).
Драйверам USB требуется наличие буферов, которые могут быть использованы для прямого доступа к памяти (DMA), хотя им не обязательно самостоятельно выполнять привязку DMA. Существуют API, применяемые при выделении DMA-буферов, поскольку они смогут предотвратить использование некорректных буферов на некоторых системах. В некоторых случаях драйверы могут использовать 64-битный режим DMA для устранения прочих видов буферных ограничений.
Примечания
Ссылки Официальный сайт The Linux USB Subsystem
Категория:Ядро Linux