Initial import, synchronized with English 1.9
Obtained from: The FreeBSD Russian Documentation Project
This commit is contained in:
parent
2a3dd2b4cb
commit
ebd62bf3da
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=24795
1 changed files with 708 additions and 0 deletions
708
ru_RU.KOI8-R/books/arch-handbook/sound/chapter.sgml
Normal file
708
ru_RU.KOI8-R/books/arch-handbook/sound/chapter.sgml
Normal file
|
@ -0,0 +1,708 @@
|
||||||
|
<!--
|
||||||
|
The FreeBSD Russian Documentation Project
|
||||||
|
|
||||||
|
$FreeBSD$
|
||||||
|
$FreeBSDru: frdp/doc/ru_RU.KOI8-R/books/arch-handbook/sound/chapter.sgml,v 1.8 2005/06/08 05:57:29 gad Exp $
|
||||||
|
|
||||||
|
Original revision: 1.9
|
||||||
|
-->
|
||||||
|
|
||||||
|
<chapter id="oss">
|
||||||
|
<chapterinfo>
|
||||||
|
<authorgroup>
|
||||||
|
<author>
|
||||||
|
<firstname>Jean-Francois</firstname>
|
||||||
|
<surname>Dockes</surname>
|
||||||
|
<contrib>Автор: </contrib>
|
||||||
|
</author>
|
||||||
|
</authorgroup>
|
||||||
|
<!-- 23 November 2001 -->
|
||||||
|
</chapterinfo>
|
||||||
|
|
||||||
|
<title>Подсистема звука</title>
|
||||||
|
|
||||||
|
<sect1 id="oss-intro">
|
||||||
|
<title>Введение</title>
|
||||||
|
|
||||||
|
<para>Перевод на русский язык: Виталий
|
||||||
|
Богданов (<email>gad@gad.glazov.net</email>)</para>
|
||||||
|
|
||||||
|
<indexterm><primary>подсистема звука</primary></indexterm>
|
||||||
|
|
||||||
|
<para>В подсистеме звука FreeBSD существует чёткое разделение
|
||||||
|
между частью, поддерживающей общие звуковые возможности и
|
||||||
|
аппаратно зависимой частью. Данная особенность делает
|
||||||
|
более простым добавление поддержки новых устройств.</para>
|
||||||
|
|
||||||
|
<para>&man.pcm.4; занимает центральное место в подсистеме
|
||||||
|
звука. Его основными элементами являются:</para>
|
||||||
|
|
||||||
|
<indexterm><primary>интерфейс системных вызовов</primary></indexterm>
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>Интерфейс системных вызовов (read, write, ioctls) к
|
||||||
|
функциям оцифрованного звука и микшера. Командный набор
|
||||||
|
ioctl совместим с интерфейсом <emphasis>OSS</emphasis>
|
||||||
|
или <emphasis>Voxware</emphasis>, позволяя тем самым
|
||||||
|
портирование мультимедиа приложений без дополнительной
|
||||||
|
модификации.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>Общий код обработки звуковых данных (преобразования
|
||||||
|
форматов, виртуальные каналы).</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>Единый программный интерфейс к аппаратно-зависимым
|
||||||
|
модулям звукового интерфейса.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>Дополнительная поддержка нескольких общих аппаратных
|
||||||
|
интерфейсов (ac97) или разделяемого аппаратно-специфичного
|
||||||
|
кода (например: функции ISA DMA).</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<para>Поддержка отдельных звуковых карт осуществляется с помощью
|
||||||
|
аппаратно-специфичных драйверов, обеспечивающих канальные и
|
||||||
|
микшерные интерфейсы, включаемые в
|
||||||
|
общий <devicename>pcm</devicename> код.</para>
|
||||||
|
|
||||||
|
<para>В этой главе термином <devicename>pcm</devicename> мы
|
||||||
|
будем называть центральную, общую часть звукового драйвера, как
|
||||||
|
противопоставление аппаратно-специфичным модулям.</para>
|
||||||
|
|
||||||
|
<para>Человек, решающий написать драйвер наверняка захочет использовать
|
||||||
|
в качестве шаблона уже существующий код. Но, если звуковой код хорош и
|
||||||
|
чист, он также в основном лишён комментариев. Этот документ - попытка
|
||||||
|
рассмотрения базового интерфейса и попытка ответить на вопросы, возникшие
|
||||||
|
при адаптировании существующего кода.</para>
|
||||||
|
|
||||||
|
<para>Для старта с рабочего примера, вы можете найти шаблон
|
||||||
|
драйвера, оснащенного комментариями на <ulink
|
||||||
|
url="http://people.FreeBSD.org/~cg/template.c">
|
||||||
|
http://people.FreeBSD.org/~cg/template.c</ulink></para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="oss-files">
|
||||||
|
<title>Файлы</title>
|
||||||
|
|
||||||
|
<para>Весь исходный код, на сегодняшний момент (FreeBSD 4.4), содержится
|
||||||
|
в каталоге <filename>/usr/src/sys/dev/sound/</filename>, за исключением
|
||||||
|
публичных определений интерфейса ioctl, находящихся в
|
||||||
|
<filename>/usr/src/sys/sys/soundcard.h</filename></para>
|
||||||
|
|
||||||
|
<para>В подкаталоге <filename>pcm/</filename> родительского
|
||||||
|
каталога <filename>/usr/src/sys/dev/sound/</filename> находится
|
||||||
|
главный код, а
|
||||||
|
в каталогах <filename>isa/</filename> и <filename>pci/</filename>
|
||||||
|
содержатся драйвера для ISA и PCI карт.</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="pcm-probe-and-attach">
|
||||||
|
<title>Обнаружение, подключение, и т.д.</title>
|
||||||
|
|
||||||
|
<para>Обнаружение и подключение звуковых драйверов во многом схоже с
|
||||||
|
драйвером любого другого устройства. За дополнительной информацией
|
||||||
|
вы можете обратиться к главам <link
|
||||||
|
linkend="isa-driver"> ISA</link> или <link
|
||||||
|
linkend="pci">PCI</link> данного руководства.</para>
|
||||||
|
|
||||||
|
<para>Но всё же, звуковые драйвера немного отличаются:</para>
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Они объявляют сами себя, как устройства класса <devicename>pcm</devicename>,
|
||||||
|
с частной структурой устройства <structname>struct
|
||||||
|
snddev_info</structname> :</para>
|
||||||
|
|
||||||
|
<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);</programlisting>
|
||||||
|
|
||||||
|
<indexterm><primary>драйвера устройств</primary><secondary>звук</secondary></indexterm>
|
||||||
|
<para>Большинство звуковых драйверов нуждаются в сохранении личной
|
||||||
|
информации, касающейся их устройства. Структура с личными
|
||||||
|
данными обычно выделяется при вызове функции attach. Её адрес
|
||||||
|
передаётся <devicename>pcm</devicename> посредством вызовов
|
||||||
|
<function>pcm_register()</function>
|
||||||
|
и <function>mixer_init()</function>. Позже
|
||||||
|
<devicename>pcm</devicename> передаёт назад этот адрес, в
|
||||||
|
качестве параметра в вызовах к интерфейсам звукового
|
||||||
|
драйвера.</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Функция подключения звукового драйвера должна объявлять
|
||||||
|
её микшерный или AC97 интерфейс
|
||||||
|
<devicename>pcm</devicename> посредством
|
||||||
|
вызова <function>mixer_init()</function>. Для микшерного
|
||||||
|
интерфейса это взамен вернёт вызов <link linkend="xxxmixer-init">
|
||||||
|
<function>xxxmixer_init()</function></link>.</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Функция подключения звукового драйвера передаёт
|
||||||
|
общие настройки каналов <devicename>pcm</devicename> посредством
|
||||||
|
вызова <function>pcm_register(dev, sc, nplay,
|
||||||
|
nrec)</function>, где <varname>sc</varname> - адрес
|
||||||
|
структуры данных устройства, используемой в дальнейших
|
||||||
|
вызовах от <devicename>pcm</devicename>, а <varname>nplay</varname>
|
||||||
|
и <varname>nrec</varname> - количество каналов проигрывания и
|
||||||
|
записи.</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Функция подключения звукового драйвера объявляет каждый
|
||||||
|
из её каналов с помощью вызовов
|
||||||
|
<function>pcm_addchan()</function>. Это установит занятость
|
||||||
|
канала в <devicename>pcm</devicename> и вызовет
|
||||||
|
взамен вызов
|
||||||
|
<link linkend="xxxchannel-init">
|
||||||
|
<function>xxxchannel_init()</function></link>.</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Функция отключения должна вызывать
|
||||||
|
<function>pcm_unregister()</function> перед объявлением её ресурсов
|
||||||
|
свободными.</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<para>Существует два метода работы с не PnP устройствами:</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>Использование метода <function>device_identify()</function>
|
||||||
|
(пример смотрите в: <filename>sound/isa/es1888.c</filename>).
|
||||||
|
<function>device_identify()</function> пытается обнаружить
|
||||||
|
оборудование, использующее известные адреса, и если найдёт
|
||||||
|
поддерживаемое устройство, то создаст новое pcm
|
||||||
|
устройство, которое затем будет передано процессу
|
||||||
|
обнаружения/подключения.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>Использование выборочной конфигурации ядра с соответствующими
|
||||||
|
хинтами для pcm устройств (пример:
|
||||||
|
<filename>sound/isa/mss.c</filename>).</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<para><devicename>pcm</devicename> драйверы должны поддерживать
|
||||||
|
<function>device_suspend</function>,
|
||||||
|
<function>device_resume</function> и
|
||||||
|
<function>device_shutdown</function> функции, для корректного
|
||||||
|
функционирования управления питанием и процесса выгрузки модуля.</para>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="oss-interfaces">
|
||||||
|
<title>Интерфейсы</title>
|
||||||
|
|
||||||
|
<para>Интерфейс между <devicename>pcm</devicename>
|
||||||
|
и звуковыми драйверами определён в терминах <link
|
||||||
|
linkend="kernel-objects">объектов ядра</link>.</para>
|
||||||
|
|
||||||
|
<para>Есть 2 основных интерфейса, которые обычно обеспечивает
|
||||||
|
звуковой драйвер: <emphasis>канальный</emphasis> и, либо
|
||||||
|
<emphasis>микшерный</emphasis> либо <emphasis>AC97</emphasis>.</para>
|
||||||
|
|
||||||
|
<para>Интерфейс <emphasis>AC97</emphasis> довольно мало использует
|
||||||
|
доступ к ресурсам оборудования (чтение/запись регистров). Данный
|
||||||
|
интерфейс реализован в драйверах для карт с кодеком AC97. В
|
||||||
|
этом случае фактический микшерный интерфейс обеспечивается разделяемым
|
||||||
|
кодом AC97 в <devicename>pcm</devicename>.</para>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>Канальный интерфейс</title>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>Общие заметки о параметрах функций</title>
|
||||||
|
|
||||||
|
<para>Звуковые драйверы обычно имеют структуру с личными
|
||||||
|
данными для описания их устройства и по одной структуре на
|
||||||
|
каждый поддерживаемый канал проигрывания или записи данных.</para>
|
||||||
|
|
||||||
|
<para>Для всех функций канального интерфейса первый параметр -
|
||||||
|
непрозрачный указатель.</para>
|
||||||
|
|
||||||
|
<para>Второй параметр это указатель на структуру с
|
||||||
|
данными канала. Исключение:
|
||||||
|
У <function>channel_init()</function> это указатель на
|
||||||
|
частную структуру устройства (данная функция возвращает
|
||||||
|
указатель на канал для дальнейшего использования
|
||||||
|
в <devicename>pcm</devicename>).</para>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>Обзор операций передачи данных</title>
|
||||||
|
|
||||||
|
<para>Для передачи данных,
|
||||||
|
<devicename>pcm</devicename> и звуковые драйвера
|
||||||
|
используют разделяемую область памяти, описанную
|
||||||
|
в <structname>struct snd_dbuf</structname>.</para>
|
||||||
|
|
||||||
|
<para><structname>struct snd_dbuf</structname> принадлежит
|
||||||
|
<devicename>pcm</devicename>, и звуковые драйверы
|
||||||
|
получают нужные значения с помощью вызовов функций
|
||||||
|
(<function>sndbuf_getxxx()</function>).</para>
|
||||||
|
|
||||||
|
<para>Область разделяемой памяти имеет размер, определяемый с помощью
|
||||||
|
<function>sndbuf_getsize()</function> и разделён на блоки
|
||||||
|
фиксированного размера, определённого в
|
||||||
|
<function>sndbuf_getblksz()</function> количества байт.</para>
|
||||||
|
|
||||||
|
<para>При проигрывании, общий механизм передачи данных примерно
|
||||||
|
следующий (обратный механизму, используемому при записи):</para>
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para> В начале, <devicename>pcm</devicename> заполняет
|
||||||
|
буфер, затем вызывает функцию звукового драйвера <link
|
||||||
|
linkend="channel-trigger">
|
||||||
|
<function>xxxchannel_trigger()</function></link>
|
||||||
|
с параметром PCMTRIG_START.</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Затем звуковой драйвер многократно передаёт всю
|
||||||
|
область памяти
|
||||||
|
(<function>sndbuf_getbuf()</function>,
|
||||||
|
<function>sndbuf_getsize()</function>) устройству, с
|
||||||
|
количеством байт, определённым в <function>sndbuf_getblksz()</function> .
|
||||||
|
Взамен это вызовет <function>chn_intr()</function>
|
||||||
|
<devicename>pcm</devicename> функцию для каждого
|
||||||
|
переданного блока (это обычно происходит во время
|
||||||
|
прерывания).</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para><function>chn_intr()</function> копирует новые
|
||||||
|
данные в область, которая была передана устройству (сейчас
|
||||||
|
свободная) и вносит соответствующие изменения в
|
||||||
|
структуру <structname>snd_dbuf</structname> .</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3 id="xxxchannel-init">
|
||||||
|
<title>channel_init</title>
|
||||||
|
|
||||||
|
<para><function>xxxchannel_init()</function> вызывается для
|
||||||
|
инициализации каждого из каналов проигрывания или
|
||||||
|
записи. Вызовы инициируются функцией подключения
|
||||||
|
звукового драйвера. (Подробнее
|
||||||
|
в главе <link linkend="pcm-probe-and-attach">
|
||||||
|
Обнаружение и подключение</link>).</para>
|
||||||
|
|
||||||
|
<programlisting> static void *
|
||||||
|
xxxchannel_init(kobj_t obj, void *data,
|
||||||
|
struct snd_dbuf *b, struct pcm_channel *c, int dir)<co id="co-chinit-params">
|
||||||
|
{
|
||||||
|
struct xxx_info *sc = data;
|
||||||
|
struct xxx_chinfo *ch;
|
||||||
|
...
|
||||||
|
return ch;<co id="co-chinit-return">
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<calloutlist>
|
||||||
|
|
||||||
|
<callout arearefs="co-chinit-params">
|
||||||
|
<para><varname>b</varname> - это адрес канальной
|
||||||
|
<structname>struct snd_dbuf</structname>. Она должна
|
||||||
|
быть инициализирована в функции посредством
|
||||||
|
вызова <function>sndbuf_alloc()</function>. Нормальный
|
||||||
|
размер буфера для использования - наименьшее кратное
|
||||||
|
размера передаваемого блока данных для вашего устройства.</para>
|
||||||
|
|
||||||
|
<para><varname>c</varname> - это
|
||||||
|
указатель на структуру
|
||||||
|
контроля <devicename>pcm</devicename> канала. Это не прозрачный
|
||||||
|
объект. Функция должна хранить его в локальной структуре
|
||||||
|
канала, для дальнейшего использования в вызовах к
|
||||||
|
<devicename>pcm</devicename> (например в:
|
||||||
|
<function>chn_intr(c)</function>).</para>
|
||||||
|
|
||||||
|
<para><varname>dir</varname> определяет для каких целей
|
||||||
|
используется канал
|
||||||
|
(<literal>PCMDIR_PLAY</literal> или
|
||||||
|
<literal>PCMDIR_REC</literal>).</para>
|
||||||
|
</callout>
|
||||||
|
|
||||||
|
<callout arearefs="co-chinit-return">
|
||||||
|
<para>Функция должна возвращать указатель на личную,
|
||||||
|
область, используемую для контроля этого
|
||||||
|
канала. Он будет передаваться в качестве параметра в
|
||||||
|
других вызовах канального интерфейса.</para>
|
||||||
|
</callout>
|
||||||
|
|
||||||
|
</calloutlist>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>channel_setformat</title>
|
||||||
|
|
||||||
|
<para><function>xxxchannel_setformat()</function> настраивает
|
||||||
|
устройство на конкретный канал определённого формата звука.</para>
|
||||||
|
|
||||||
|
<programlisting> static int
|
||||||
|
xxxchannel_setformat(kobj_t obj, void *data, u_int32_t format)<co id="co-chsetformat-params">
|
||||||
|
{
|
||||||
|
struct xxx_chinfo *ch = data;
|
||||||
|
...
|
||||||
|
return 0;
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<calloutlist>
|
||||||
|
<callout arearefs="co-chsetformat-params">
|
||||||
|
<para><varname>format</varname> используется, как
|
||||||
|
<literal>AFMT_XXX значение</literal>
|
||||||
|
(<filename>soundcard.h</filename>).</para>
|
||||||
|
</callout>
|
||||||
|
|
||||||
|
</calloutlist>
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>channel_setspeed</title>
|
||||||
|
|
||||||
|
<para><function>xxxchannel_setspeed()</function> устанавливает
|
||||||
|
оборудование канала на определённую шаблонную скорость и возвращает
|
||||||
|
возможную корректирующую скорость.</para>
|
||||||
|
|
||||||
|
<programlisting> static int
|
||||||
|
xxxchannel_setspeed(kobj_t obj, void *data, u_int32_t speed)
|
||||||
|
{
|
||||||
|
struct xxx_chinfo *ch = data;
|
||||||
|
...
|
||||||
|
return speed;
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>channel_setblocksize</title>
|
||||||
|
|
||||||
|
<para><function>xxxchannel_setblocksize()</function> устанавливает
|
||||||
|
размер передаваемого блока между
|
||||||
|
<devicename>pcm</devicename> и звуковым драйвером, и между
|
||||||
|
звуковым драйвером и устройством. Обычно это будет количество
|
||||||
|
переданных байт перед прерыванием. Во время трансфера звуковой
|
||||||
|
драйвер должен должен вызывать
|
||||||
|
<devicename>pcm</devicename> функцию <function>chn_intr()</function> каждый
|
||||||
|
раз при передаче блока данных такого размера.</para>
|
||||||
|
|
||||||
|
<para>Большинство звуковых драйверов только берут на заметку
|
||||||
|
размер блока для использования во время передачи данных.</para>
|
||||||
|
|
||||||
|
<programlisting> static int
|
||||||
|
xxxchannel_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
|
||||||
|
{
|
||||||
|
struct xxx_chinfo *ch = data;
|
||||||
|
...
|
||||||
|
return blocksize;<co id="co-chsetblocksize-return">
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<calloutlist>
|
||||||
|
<callout arearefs="co-chsetblocksize-return">
|
||||||
|
<para>Функция возвращает возможно согласованный размер
|
||||||
|
блока. В случае, если размер блока действительно
|
||||||
|
изменился должен быть произведён вызов
|
||||||
|
<function>sndbuf_resize()</function> для корректирования
|
||||||
|
буфера.</para>
|
||||||
|
|
||||||
|
</callout>
|
||||||
|
</calloutlist>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3 id="channel-trigger">
|
||||||
|
<title>channel_trigger</title>
|
||||||
|
|
||||||
|
<para><function>xxxchannel_trigger()</function> вызывается
|
||||||
|
<devicename>pcm</devicename> для контроля над трансферными
|
||||||
|
операциями в драйвере.</para>
|
||||||
|
|
||||||
|
<programlisting> static int
|
||||||
|
xxxchannel_trigger(kobj_t obj, void *data, int go)<co id="co-chtrigger-params">
|
||||||
|
{
|
||||||
|
struct xxx_chinfo *ch = data;
|
||||||
|
...
|
||||||
|
return 0;
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<calloutlist>
|
||||||
|
<callout arearefs="co-chtrigger-params">
|
||||||
|
<para><varname>go</varname> определяет действие для
|
||||||
|
текущего вызова. Возможные значения:</para>
|
||||||
|
<itemizedlist>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para><literal>PCMTRIG_START</literal>: драйвер
|
||||||
|
должен начать передачу данных из или в канальный
|
||||||
|
буфер. Буфер и его размер могут быть получены через
|
||||||
|
вызов <function>sndbuf_getbuf()</function> и
|
||||||
|
<function>sndbuf_getsize()</function>.</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para><literal>PCMTRIG_EMLDMAWR</literal> /
|
||||||
|
<literal>PCMTRIG_EMLDMARD</literal>: говорит
|
||||||
|
драйверу, что входной или выходной буфер возможно
|
||||||
|
был обновлён. Большинство драйверов игнорируют
|
||||||
|
эти вызовы.</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para><literal>PCMTRIG_STOP</literal> /
|
||||||
|
<literal>PCMTRIG_ABORT</literal>: драйвер должен
|
||||||
|
остановить текущую передачу данных.</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
</callout>
|
||||||
|
</calloutlist>
|
||||||
|
|
||||||
|
<note><para>Если драйвер использует ISA DMA,
|
||||||
|
<function>sndbuf_isadma()</function> должна вызываться
|
||||||
|
перед выполнением действий над устройством, она также
|
||||||
|
позаботится о вещах со стороны DMA чипа.</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>channel_getptr</title>
|
||||||
|
|
||||||
|
<para><function>xxxchannel_getptr()</function> возвращает
|
||||||
|
текущее смещение в передаваемом буфере. Обычно вызывается
|
||||||
|
в <function>chn_intr()</function>, и так
|
||||||
|
<devicename>pcm</devicename> узнаёт, где брать данные для
|
||||||
|
новой передачи.</para>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>channel_free</title>
|
||||||
|
|
||||||
|
<para><function>xxxchannel_free()</function> вызывается для
|
||||||
|
освобождения ресурсов канала. Например: должна вызываться,
|
||||||
|
при выгрузке драйвера, если структуры данных канала
|
||||||
|
распределялись динамично или, если
|
||||||
|
<function>sndbuf_alloc()</function> не использовалась
|
||||||
|
для выделения памяти под буфер.</para>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>channel_getcaps</title>
|
||||||
|
|
||||||
|
<programlisting> struct pcmchan_caps *
|
||||||
|
xxxchannel_getcaps(kobj_t obj, void *data)
|
||||||
|
{
|
||||||
|
return &xxx_caps;<co id="co-chgetcaps-return">
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<calloutlist>
|
||||||
|
|
||||||
|
<callout arearefs="co-chgetcaps-return">
|
||||||
|
<para>Подпрограмма возвращает указатель на (обычно
|
||||||
|
статически-определяемую) структуру
|
||||||
|
<structname>pcmchan_caps</structname> (описанную в
|
||||||
|
<filename>sound/pcm/channel.h</filename>. Структура содержит
|
||||||
|
данные о минимуме и максимуме шаблонных частот и
|
||||||
|
воспринимаемых звуковых форматах. Для примера смотрите
|
||||||
|
исходный код любого звукового драйвера.</para>
|
||||||
|
</callout>
|
||||||
|
|
||||||
|
</calloutlist>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>Другие функции</title>
|
||||||
|
|
||||||
|
<para><function>channel_reset()</function>,
|
||||||
|
<function>channel_resetdone()</function>, и
|
||||||
|
<function>channel_notify()</function> предназначены для
|
||||||
|
специальных целей и не должны употребляться в драйвере
|
||||||
|
без обсуждения с авторами (&a.cg;).</para>
|
||||||
|
|
||||||
|
<para><function>channel_setdir()</function> is deprecated.</para>
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>Микшерный интерфейс</title>
|
||||||
|
|
||||||
|
<sect3 id="xxxmixer-init">
|
||||||
|
<title>mixer_init</title>
|
||||||
|
|
||||||
|
<para><function>xxxmixer_init()</function> инициализирует
|
||||||
|
оборудование и говорит <devicename>pcm</devicename> какие микшерные
|
||||||
|
устройства доступны для проигрывания и записи</para>
|
||||||
|
|
||||||
|
<programlisting> 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]<co id="co-mxini-sd">
|
||||||
|
mix_setdevs(m, v);
|
||||||
|
[Set appropriate bits in v for record mixers]
|
||||||
|
mix_setrecdevs(m, v)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<calloutlist>
|
||||||
|
<callout arearefs="co-mxini-sd">
|
||||||
|
<para>Устанавливает биты в целом значении и вызывает
|
||||||
|
<function>mix_setdevs()</function> и
|
||||||
|
<function>mix_setrecdevs()</function> чтобы сообщить
|
||||||
|
<devicename>pcm</devicename> какие устройства существуют.</para>
|
||||||
|
</callout>
|
||||||
|
</calloutlist>
|
||||||
|
|
||||||
|
<para>Определения битов микшера могут быть найдены в
|
||||||
|
<filename>soundcard.h</filename>
|
||||||
|
(<literal>SOUND_MASK_XXX</literal> значения и
|
||||||
|
<literal>SOUND_MIXER_XXX</literal> битовые сдвиги).</para>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>mixer_set</title>
|
||||||
|
|
||||||
|
<para><function>xxxmixer_set()</function> устанавливает уровень
|
||||||
|
громкости для одного микшерного устройства.</para>
|
||||||
|
|
||||||
|
<programlisting> static int
|
||||||
|
xxxmixer_set(struct snd_mixer *m, unsigned dev,
|
||||||
|
unsigned left, unsigned right)<co id="co-mxset-params">
|
||||||
|
{
|
||||||
|
struct sc_info *sc = mix_getdevinfo(m);
|
||||||
|
[set volume level]
|
||||||
|
return left | (right << 8);<co id="co-mxset-return">
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<calloutlist>
|
||||||
|
<callout arearefs="co-mxset-params">
|
||||||
|
<para>Устройство определяется, как <literal>SOUND_MIXER_XXX</literal>
|
||||||
|
значение</para> <para>Допустимые значения уровней громкости лежат
|
||||||
|
в пределах [0-100]. Равное нулю значение должно выключать звук
|
||||||
|
устройства.</para>
|
||||||
|
</callout>
|
||||||
|
|
||||||
|
<callout arearefs="co-mxset-return">
|
||||||
|
<para>Вероятно уровни оборудования не будут совпадать с
|
||||||
|
входной шкалой, и будет происходить некоторое округление, подпрограмма
|
||||||
|
будет возвращает точные значения (в промежутке 0-100), как уже
|
||||||
|
было сказано.</para>
|
||||||
|
</callout>
|
||||||
|
</calloutlist>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>mixer_setrecsrc</title>
|
||||||
|
|
||||||
|
<para><function>xxxmixer_setrecsrc()</function> устанавливает
|
||||||
|
исходное записывающее устройство.</para>
|
||||||
|
|
||||||
|
<programlisting> static int
|
||||||
|
xxxmixer_setrecsrc(struct snd_mixer *m, u_int32_t src)<co id="co-mxsr-params">
|
||||||
|
{
|
||||||
|
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;<co id="co-mxsr-return">
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<calloutlist>
|
||||||
|
<callout arearefs="co-mxsr-params">
|
||||||
|
<para>Желаемые записывающие устройства указываются в битовом поле</para>
|
||||||
|
</callout>
|
||||||
|
|
||||||
|
<callout arearefs="co-mxsr-return">
|
||||||
|
<para>Возвращается фактический набор устройств для записи.
|
||||||
|
Некоторые драйверы могут устанавливать только одно устройство для
|
||||||
|
записи. Функция должна возвращать -1, в случае возникновения
|
||||||
|
ошибки.</para>
|
||||||
|
</callout>
|
||||||
|
</calloutlist>
|
||||||
|
</sect3>
|
||||||
|
|
||||||
|
<sect3>
|
||||||
|
<title>mixer_uninit, mixer_reinit</title>
|
||||||
|
|
||||||
|
<para><function>xxxmixer_uninit()</function> должна проверить,
|
||||||
|
что все звуки выключены (mute), и, если возможно выключить
|
||||||
|
оборудование микшера </para>
|
||||||
|
|
||||||
|
<para><function>xxxmixer_reinit()</function> должна удостовериться,
|
||||||
|
что оборудование микшера включено и все установки, неконтролируемые
|
||||||
|
<function>mixer_set()</function> или
|
||||||
|
<function>mixer_setrecsrc()</function> восстановлены.</para>
|
||||||
|
|
||||||
|
</sect3>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>Интерфейс AC97</title>
|
||||||
|
|
||||||
|
<indexterm><primary>AC97</primary></indexterm>
|
||||||
|
|
||||||
|
<para>Поддержка интерфейса <emphasis>AC97</emphasis> осуществляется
|
||||||
|
драйверами с кодеком AC97. Он поддерживает только три метода:</para>
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
|
||||||
|
<listitem><para><function>xxxac97_init()</function> возвращает
|
||||||
|
количество найденных ac97 кодеков.</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem><para><function>ac97_read()</function> и
|
||||||
|
<function>ac97_write()</function> читают или записывают
|
||||||
|
данные определенного регистра.</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<para>Интерфейс <emphasis>AC97</emphasis> используется кодом
|
||||||
|
AC97 в <devicename>pcm</devicename> для выполнения операций
|
||||||
|
более высокого уровня. За примером обращайтесь к
|
||||||
|
<filename>sound/pci/maestro3.c</filename> или к другим
|
||||||
|
файлам из каталога <filename>sound/pci/</filename>.</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Local Variables:
|
||||||
|
mode: sgml
|
||||||
|
sgml-declaration: "../chapter.decl"
|
||||||
|
sgml-indent-data: t
|
||||||
|
sgml-omittag: nil
|
||||||
|
sgml-always-quote-attributes: t
|
||||||
|
sgml-parent-document: ("../book.sgml" "part" "chapter")
|
||||||
|
End:
|
||||||
|
-->
|
Loading…
Reference in a new issue