Разработка драйвера

Раздел дает понимание роли драйвера в аудио стеке

Раздел содержит:

Обзор аудио стека
Разработка драйвера
Внутренние (private) типы данных
Пользовательские типы данных
ctrl_init()
ctrl_destroy()
Отладка драйвера

Обзор аудио стека

Рассмотрим организацию аудио стека на примере отправки приложением информацию звуковой карте. На уровне архитектуры это выглядит следующим образом:

architecture.png
Рисунок 1. Роль драйвера в аудио стеке

Все, что находится по правую сторону от разделителя – аудио драйвер. Для поддержки аудио устройства требуется наличие лишь библиотеки драйвера. Данный раздел описывает общие подходы к его разработке.

Аудиоприложение
Подготавливает PCM данные, затем выполняет несколько вызовов API для их отправки звуковой карте (устройству).
Пользовательская библиотека (libasound)
Переводит API вызовы в сообщения и отправляет их процессу драйвера.

Также клиентская библиотека имеет несколько плагинов, которые приложение может использовать для конвертации между различными форматами. Это означает, что самому драйверу необходимо поддерживать только "родные" звуковые форматы, а плагины могут использоваться для любых необходимых конвертаций. Механизм, который позволяет это осуществлять и упрощать интерфейс драйвера, выходит за рамки рассмотрения этого документа.
io-audio
Менеджер аудио стека и его драйверов, поддерживающий несколько звуковых карт одновременно. Дополнительная информация доступна на странице io-audio.
Библиотека поддержки драйверов (libado)
Предоставляет несколько подпрограмм, которые необходимы io-audio и библиотекам драйверов. Библиотека libado не поставляется отдельным файлом, вместо этого она влинкована в менеджер io-audio.
Библиотека драйвера
Модуль, разрабатываемый для конкретного устройства (семейства устройств). Является мостом между аппаратным обеспечением и аудио стеком. Согласно архитектуре аудио стека, количество кода в данном модуле небольшое. Драйвер представляет собой динамическую библиотеку и io-audio может загружать/удалять его во время выполнения.
Библиотека микшера
Если карта имеет стандарный кодек, можно использовать библиотеку микшера для уменьшения необходимой работы по разработке драйвера. Подробнее см. основные виды кодеков.

Разработка драйвера

Рассмотрим основы разработки аудио драйвера.

Внутренние (private) типы данных

API для аудио стека включает несколько внутренних структур менеджера io-audio, причем содержание известно только стеку. Следует просто сохранить указатели на них и передавать функциям, которым они необходимы.

Ниже приведен список приватных типов данных:

Префикс ado означает "аудио".

Пользовательские типы данных

Драйверу может понадобиться сохранить внутренние данные для последующего использования. Аудио стек позволяет определять конекстно-зависимые данные как для аппаратного обеспечения, так и для микшеров.

Для того, чтобы сделать API более гибким (и читаемым) стек использует следующие типы, которые можно определить по своему желанию:

HW_CONTEXT_T
Данные, которые необходимо ассоциировать с аппаратным обеспечением.
MIXER_CONTEXT_T
Данные, которые необходимо ассоциировать с микшером.

По умолчанию эти типы представляют собой пустые структуры. Через директиву #define их следует определить до включения любого из заголовочных файлов аудио стека. Например:

#define HW_CONTEXT_T my_hw_context_t
#define MIXER_CONTEXT_T my_mixer_context_t

При желании можно даже определить HW_CONTEXT_T и MIXER_CONTEXT_T как один тип.


Note: The MIXER_CONTEXT_T хранится как часть структры ado_mixer_t. Для доступа к контексту микшера необходимо вызвать ado_mixer_get_context(), потому что ado_mixer_t – внутренний тип данных менеджера io-audio.

ctrl_init()

Драйвер должен указать точку входа вызовом ctrl_init() типа ado_ctrl_dll_init_t. Когда io-audio загружает драйвер, первой будет вызвана именно ctrl_init():

int32_t ctrl_init( HW_CONTEXT_T **hw_context,
ado_card_t *card,
char *args );

Аргументы:

hw_context
Место, где функция ctrl_init() может хранить указатель на структуру состояния устройства. Можно определить HW_CONTEXT_T как произвольную структуру. По умолчанию она определена как структура hw_context.
card
Указатель на внутреннюю стурктуру ado_card_t. Структура является приватной и ее содержание известно только менеджеру io-audio. Необходимо сохранить этот указатель для передачи в другие функции в качестве аргумента, например, в ado_mixer_create().
args
Аргументы командной строки, которые были переданы при вызове io-audio или mount.

Первое, что необходимо сделать при инициализации – выделить контекстно-зависимую структуру состояния путем вызова ado_calloc() или ado_malloc().

Затем необходимо определить, присутствует ли поддерживаемое оборудование в системе. Точный способ зависит от драйвера и в некоторых случаях это вовсе невозможно:

После этого следует задать короткое и длинное имена, которые приложения будут использовать для определения типа карты и имени конкретного экземпляра. Это доступно через вызовы ado_card_set_shortname() и ado_card_set_longname().

Инициализация также зависит от того, какие функции поддерживает драйвер:

Если инициализация была успешной ctrl_init() должна вернуть 0 и -1 в случае ошибки (в этом случае io-audio освободит устройство и отмонтирует его драйвер).

ctrl_destroy()

Драйвер также должен определить точку входа ctrl_destroy() типа ado_ctrl_dll_destroy_t. Менеджер io-audio вызывает ctrl_destroy() независимо от того, была ли карта отмонтирована:

int32_t ctrl_destroy( HW_CONTEXT_T **hw_context );

Callback-функция должна отменить действия, которые выполнены в ctrl_init(), что обычно включает:

Если освобождение устройства было успешным, ctrl_destroy() должна вернуть 0 и -1 в случае ошибки.

Отладка драйвера

Аудио стек использует несколько констант для включения и выключения отладочных сообщений. Главная из них - ADO_DEBUG.

Стандартные make-файлы аудио стека позволяют задать переменную ADO_DEBUG, если в окружении определена переменная DEBUG. Если компилируется отладочная версия драйвера, ADO_DEBUG также будет определена для помощи в отладке.

Если определена ADO_DEBUG, происходит следующее:

Если установлена ADO_DEBUG, также можно определить макрос для включения специализированного отладочного вывода:

Эти макросы позволяют отлаживать логику использования мьютексов и rw-блокировок.


Caution: Если драйвер скомпилирован с переменной ADO_DEBUG, драйвер не будет работать под управлением штатного менеджера io-audio. Для этого следует использовать io-audio_g.




Предыдущий раздел: Библиотека libado