diff options
Diffstat (limited to 'documentation/content/ru/books/arch-handbook/sound/chapter.adoc')
| -rw-r--r-- | documentation/content/ru/books/arch-handbook/sound/chapter.adoc | 432 |
1 files changed, 0 insertions, 432 deletions
diff --git a/documentation/content/ru/books/arch-handbook/sound/chapter.adoc b/documentation/content/ru/books/arch-handbook/sound/chapter.adoc deleted file mode 100644 index 4bb8b82ea9..0000000000 --- a/documentation/content/ru/books/arch-handbook/sound/chapter.adoc +++ /dev/null @@ -1,432 +0,0 @@ ---- -title: Глава 15. Подсистема звука -authors: ---- - -[[oss]] -= Подсистема звука -:doctype: book -:toc: macro -:toclevels: 1 -:icons: font -:sectnums: -:sectnumlevels: 6 -:sectnumoffset: 15 -:partnums: -:source-highlighter: rouge -:experimental: - -ifdef::env-beastie[] -ifdef::backend-html5[] -:imagesdir: ../../../../images/{images-path} -endif::[] -ifndef::book[] -include::shared/authors.adoc[] -include::shared/mirrors.adoc[] -include::shared/releases.adoc[] -include::shared/attributes/attributes-{{% lang %}}.adoc[] -include::shared/{{% lang %}}/teams.adoc[] -include::shared/{{% lang %}}/mailing-lists.adoc[] -include::shared/{{% lang %}}/urls.adoc[] -toc::[] -endif::[] -ifdef::backend-pdf,backend-epub3[] -include::../../../../../shared/asciidoctor.adoc[] -endif::[] -endif::[] - -ifndef::env-beastie[] -toc::[] -include::../../../../../shared/asciidoctor.adoc[] -endif::[] - -[[oss-intro]] -== Введение - -Перевод на русский язык: Виталий Богданов (mailto:gad@gad.glazov.net[gad@gad.glazov.net]) - -В подсистеме звука FreeBSD существует чёткое разделение между частью, поддерживающей общие звуковые возможности и аппаратно зависимой частью. Данная особенность делает более простым добавление поддержки новых устройств. - -man:pcm[4] занимает центральное место в подсистеме звука. Его основными элементами являются: - -* Интерфейс системных вызовов (read, write, ioctls) к функциям оцифрованного звука и микшера. Командный набор ioctl совместим с интерфейсом _OSS_ или _Voxware_, позволяя тем самым портирование мультимедиа приложений без дополнительной модификации. -* Общий код обработки звуковых данных (преобразования форматов, виртуальные каналы). -* Единый программный интерфейс к аппаратно-зависимым модулям звукового интерфейса. -* Дополнительная поддержка нескольких общих аппаратных интерфейсов (ac97) или разделяемого аппаратно-специфичного кода (например: функции ISA DMA). - -Поддержка отдельных звуковых карт осуществляется с помощью аппаратно-специфичных драйверов, обеспечивающих канальные и микшерные интерфейсы, включаемые в общий код. - -В этой главе термином мы будем называть центральную, общую часть звукового драйвера, как противопоставление аппаратно-специфичным модулям. - -Человек, решающий написать драйвер наверняка захочет использовать в качестве шаблона уже существующий код. Но, если звуковой код хорош и чист, он также в основном лишён комментариев. Этот документ - попытка рассмотрения базового интерфейса и попытка ответить на вопросы, возникшие при адаптировании существующего кода. - -Для старта с рабочего примера, вы можете найти шаблон драйвера, оснащенного комментариями на http://people.FreeBSD.org/\~cg/template.c[ http://people.FreeBSD.org/~cg/template.c] - -[[oss-files]] -== Файлы - -Весь исходный код, на сегодняшний момент (FreeBSD 4.4), содержится в каталоге [.filename]#/usr/src/sys/dev/sound/#, за исключением публичных определений интерфейса ioctl, находящихся в [.filename]#/usr/src/sys/sys/soundcard.h# - -В подкаталоге [.filename]#pcm/# родительского каталога [.filename]#/usr/src/sys/dev/sound/# находится главный код, а в каталогах [.filename]#isa/# и [.filename]#pci/# содержатся драйвера для ISA и PCI карт. - -[[pcm-probe-and-attach]] -== Обнаружение, подключение, и т.д. - -Обнаружение и подключение звуковых драйверов во многом схоже с драйвером любого другого устройства. За дополнительной информацией вы можете обратиться к главам <<isa-driver, ISA>> или <<pci,PCI>> данного руководства. - -Но всё же, звуковые драйвера немного отличаются: - -* Они объявляют сами себя, как устройства класса , с частной структурой устройства : -+ -[.programlisting] -.... - static driver_t xxx_driver = { - "pcm", - xxx_methods, - sizeof(struct snddev_info) - }; - - DRIVER_MODULE(snd_xxxpci, pci, xxx_driver, pcm_devclass, 0, 0); - MODULE_DEPEND(snd_xxxpci, snd_pcm, PCM_MINVER, PCM_PREFVER,PCM_MAXVER); -.... -+ -Большинство звуковых драйверов нуждаются в сохранении личной информации, касающейся их устройства. Структура с личными данными обычно выделяется при вызове функции attach. Её адрес передаётся посредством вызовов `pcm_register()` и `mixer_init()`. Позже передаёт назад этот адрес, в качестве параметра в вызовах к интерфейсам звукового драйвера. -* Функция подключения звукового драйвера должна объявлять её микшерный или AC97 интерфейс посредством вызова `mixer_init()`. Для микшерного интерфейса это взамен вернёт вызов <<xxxmixer-init,`xxxmixer_init()`>>. -* Функция подключения звукового драйвера передаёт общие настройки каналов посредством вызова `pcm_register(dev, sc, nplay, nrec)`, где `sc` - адрес структуры данных устройства, используемой в дальнейших вызовах от , а `nplay` и `nrec` - количество каналов проигрывания и записи. -* Функция подключения звукового драйвера объявляет каждый из её каналов с помощью вызовов `pcm_addchan()`. Это установит занятость канала в и вызовет взамен вызов <<xxxchannel-init,`xxxchannel_init()`>>. -* Функция отключения должна вызывать `pcm_unregister()` перед объявлением её ресурсов свободными. - -Существует два метода работы с не PnP устройствами: - -* Использование метода `device_identify()` (пример смотрите в: [.filename]#sound/isa/es1888.c#). `device_identify()` пытается обнаружить оборудование, использующее известные адреса, и если найдёт поддерживаемое устройство, то создаст новое pcm устройство, которое затем будет передано процессу обнаружения/подключения. -* Использование выборочной конфигурации ядра с соответствующими хинтами для pcm устройств (пример: [.filename]#sound/isa/mss.c#). - -драйверы должны поддерживать `device_suspend`, `device_resume` и `device_shutdown` функции, для корректного функционирования управления питанием и процесса выгрузки модуля. - -[[oss-interfaces]] -== Интерфейсы - -Интерфейс между и звуковыми драйверами определён в терминах <<kernel-objects,объектов ядра>>. - -Есть 2 основных интерфейса, которые обычно обеспечивает звуковой драйвер: _канальный_ и, либо _микшерный_ либо _AC97_. - -Интерфейс _AC97_ довольно мало использует доступ к ресурсам оборудования (чтение/запись регистров). Данный интерфейс реализован в драйверах для карт с кодеком AC97. В этом случае фактический микшерный интерфейс обеспечивается разделяемым кодом AC97 в . - -=== Канальный интерфейс - -==== Общие заметки о параметрах функций - -Звуковые драйверы обычно имеют структуру с личными данными для описания их устройства и по одной структуре на каждый поддерживаемый канал проигрывания или записи данных. - -Для всех функций канального интерфейса первый параметр - непрозрачный указатель. - -Второй параметр это указатель на структуру с данными канала. Исключение: У ``channel_init()`` это указатель на частную структуру устройства (данная функция возвращает указатель на канал для дальнейшего использования в ). - -==== Обзор операций передачи данных - -Для передачи данных, и звуковые драйвера используют разделяемую область памяти, описанную в . - -принадлежит , и звуковые драйверы получают нужные значения с помощью вызовов функций (`sndbuf_getxxx()`). - -Область разделяемой памяти имеет размер, определяемый с помощью `sndbuf_getsize()` и разделён на блоки фиксированного размера, определённого в `sndbuf_getblksz()` количества байт. - -При проигрывании, общий механизм передачи данных примерно следующий (обратный механизму, используемому при записи): - -* В начале, заполняет буфер, затем вызывает функцию звукового драйвера <<channel-trigger,``xxxchannel_trigger()``>> с параметром PCMTRIG_START. -* Затем звуковой драйвер многократно передаёт всю область памяти (`sndbuf_getbuf()`, `sndbuf_getsize()`) устройству, с количеством байт, определённым в `sndbuf_getblksz()` . Взамен это вызовет `chn_intr()` функцию для каждого переданного блока (это обычно происходит во время прерывания). -* `chn_intr()` копирует новые данные в область, которая была передана устройству (сейчас свободная) и вносит соответствующие изменения в структуру . - -[[xxxchannel-init]] -=== channel_init - -`xxxchannel_init()` вызывается для инициализации каждого из каналов проигрывания или записи. Вызовы инициируются функцией подключения звукового драйвера. (Подробнее в главе <<pcm-probe-and-attach, Обнаружение и подключение>>). - -[.programlisting] -.... - static void * - xxxchannel_init(kobj_t obj, void *data, - struct snd_dbuf *b, struct pcm_channel *c, int dir) - { - struct xxx_info *sc = data; - struct xxx_chinfo *ch; - ... - return ch; - } - - b - это адрес канальной - struct snd_dbuf. Она должна - быть инициализирована в функции посредством - вызова sndbuf_alloc(). Нормальный - размер буфера для использования - наименьшее кратное - размера передаваемого блока данных для вашего устройства. - - c - это - указатель на структуру - контроля pcm канала. Это не прозрачный - объект. Функция должна хранить его в локальной структуре - канала, для дальнейшего использования в вызовах к - pcm (например в: - chn_intr(c)). - - dir определяет для каких целей - используется канал - (PCMDIR_PLAY или - PCMDIR_REC). - - Функция должна возвращать указатель на личную, - область, используемую для контроля этого - канала. Он будет передаваться в качестве параметра в - других вызовах канального интерфейса. - - channel_setformat - - xxxchannel_setformat() настраивает - устройство на конкретный канал определённого формата звука. - - static int - xxxchannel_setformat(kobj_t obj, void *data, u_int32_t format) - { - struct xxx_chinfo *ch = data; - ... - return 0; - } - - format используется, как - AFMT_XXX значение - (soundcard.h). - - channel_setspeed - - xxxchannel_setspeed() устанавливает - оборудование канала на определённую шаблонную скорость и возвращает - возможную корректирующую скорость. - - static int - xxxchannel_setspeed(kobj_t obj, void *data, u_int32_t speed) - { - struct xxx_chinfo *ch = data; - ... - return speed; - } - - channel_setblocksize - - xxxchannel_setblocksize() устанавливает - размер передаваемого блока между - pcm и звуковым драйвером, и между - звуковым драйвером и устройством. Обычно это будет количество - переданных байт перед прерыванием. Во время трансфера звуковой - драйвер должен должен вызывать - pcm функцию chn_intr() каждый - раз при передаче блока данных такого размера. - - Большинство звуковых драйверов только берут на заметку - размер блока для использования во время передачи данных. - - static int - xxxchannel_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) - { - struct xxx_chinfo *ch = data; - ... - return blocksize; - } - - Функция возвращает возможно согласованный размер - блока. В случае, если размер блока действительно - изменился должен быть произведён вызов - sndbuf_resize() для корректирования - буфера. - - channel_trigger - - xxxchannel_trigger() вызывается - pcm для контроля над трансферными - операциями в драйвере. - - static int - xxxchannel_trigger(kobj_t obj, void *data, int go) - { - struct xxx_chinfo *ch = data; - ... - return 0; - } - - go определяет действие для - текущего вызова. Возможные значения: - - PCMTRIG_START: драйвер - должен начать передачу данных из или в канальный - буфер. Буфер и его размер могут быть получены через - вызов sndbuf_getbuf() и - sndbuf_getsize(). - - PCMTRIG_EMLDMAWR / - PCMTRIG_EMLDMARD: говорит - драйверу, что входной или выходной буфер возможно - был обновлён. Большинство драйверов игнорируют - эти вызовы. - - PCMTRIG_STOP / - PCMTRIG_ABORT: драйвер должен - остановить текущую передачу данных. - - Если драйвер использует ISA DMA, - sndbuf_isadma() должна вызываться - перед выполнением действий над устройством, она также - позаботится о вещах со стороны DMA чипа. - - channel_getptr - - xxxchannel_getptr() возвращает - текущее смещение в передаваемом буфере. Обычно вызывается - в chn_intr(), и так - pcm узнаёт, где брать данные для - новой передачи. - - channel_free - - xxxchannel_free() вызывается для - освобождения ресурсов канала. Например: должна вызываться, - при выгрузке драйвера, если структуры данных канала - распределялись динамично или, если - sndbuf_alloc() не использовалась - для выделения памяти под буфер. - - channel_getcaps - - struct pcmchan_caps * - xxxchannel_getcaps(kobj_t obj, void *data) - { - return xxx_caps; - } - - Подпрограмма возвращает указатель на (обычно - статически-определяемую) структуру - pcmchan_caps (описанную в - sound/pcm/channel.h. Структура содержит - данные о минимуме и максимуме шаблонных частот и - воспринимаемых звуковых форматах. Для примера смотрите - исходный код любого звукового драйвера. - - Другие функции - - channel_reset(), - channel_resetdone(), и - channel_notify() предназначены для - специальных целей и не должны употребляться в драйвере - без обсуждения с авторами ({cg}). - - channel_setdir() is deprecated. - - Микшерный интерфейс - - mixer_init - - xxxmixer_init() инициализирует - оборудование и говорит pcm какие микшерные - устройства доступны для проигрывания и записи - - static int - xxxmixer_init(struct snd_mixer *m) - { - struct xxx_info *sc = mix_getdevinfo(m); - u_int32_t v; - - [Initialize hardware] - - [Set appropriate bits in v for play mixers] - mix_setdevs(m, v); - [Set appropriate bits in v for record mixers] - mix_setrecdevs(m, v) - - return 0; - } - - Устанавливает биты в целом значении и вызывает - mix_setdevs() и - mix_setrecdevs() чтобы сообщить - pcm какие устройства существуют. - - Определения битов микшера могут быть найдены в - soundcard.h - (SOUND_MASK_XXX значения и - SOUND_MIXER_XXX битовые сдвиги). - - mixer_set - - xxxmixer_set() устанавливает уровень - громкости для одного микшерного устройства. - - static int - xxxmixer_set(struct snd_mixer *m, unsigned dev, - unsigned left, unsigned right) - { - struct sc_info *sc = mix_getdevinfo(m); - [set volume level] - return left | (right 8); - } - - Устройство определяется, как SOUND_MIXER_XXX - значение Допустимые значения уровней громкости лежат - в пределах [0-100]. Равное нулю значение должно выключать звук - устройства. - - Вероятно уровни оборудования не будут совпадать с - входной шкалой, и будет происходить некоторое округление, подпрограмма - будет возвращает точные значения (в промежутке 0-100), как уже - было сказано. - - mixer_setrecsrc - - xxxmixer_setrecsrc() устанавливает - исходное записывающее устройство. - - static int - xxxmixer_setrecsrc(struct snd_mixer *m, u_int32_t src) - { - struct xxx_info *sc = mix_getdevinfo(m); - - [look for non zero bit(s) in src, set up hardware] - - [update src to reflect actual action] - return src; - } - - Желаемые записывающие устройства указываются в битовом поле - - Возвращается фактический набор устройств для записи. - Некоторые драйверы могут устанавливать только одно устройство для - записи. Функция должна возвращать -1, в случае возникновения - ошибки. - - mixer_uninit, mixer_reinit - - xxxmixer_uninit() должна проверить, - что все звуки выключены (mute), и, если возможно выключить - оборудование микшера - - xxxmixer_reinit() должна удостовериться, - что оборудование микшера включено и все установки, неконтролируемые - mixer_set() или - mixer_setrecsrc() восстановлены. - - Интерфейс AC97 - - AC97 - - Поддержка интерфейса AC97 осуществляется - драйверами с кодеком AC97. Он поддерживает только три метода: - - xxxac97_init() возвращает - количество найденных ac97 кодеков. - - ac97_read() и - ac97_write() читают или записывают - данные определенного регистра. - - Интерфейс AC97 используется кодом - AC97 в pcm для выполнения операций - более высокого уровня. За примером обращайтесь к - sound/pci/maestro3.c или к другим - файлам из каталога sound/pci/. -.... |
