Linux устройство pc speaker

Содержание
  1. PC speaker (Русский)
  2. Contents
  3. Отключение PC Speaker
  4. Глобально
  5. Терминал
  6. Постраничный вывод утилитой Less
  7. GNOME
  8. Cinnamon
  9. Установка
  10. Доступ для обычных (non-root) пользователей
  11. Полезные советы
  12. PC speaker
  13. Contents
  14. Disable PC Speaker
  15. Globally
  16. Console
  17. Less pager
  18. GNOME
  19. KDE Plasma
  20. Cinnamon
  21. PulseAudio
  22. Installation
  23. Run as non-root user
  24. Tips and Tricks
  25. Персональный блог Толика Панкова
  26. Стихи, рассказы, философия, IT, политика, панкизм, раздолбайство и болтовня.
  27. После прочтения 126 заголовков, созданных генератором новостей, Николя Саркози объявил национал-предателем высокопоставленного заокеанского покровителя майора Евсюкова
  28. PC-speaker в Linux, или как сделать beep из консоли встроенным динамиком ПК
  29. Linux устройство pc speaker
  30. PC speaker: общие сведения
  31. PIC расшифровывается как программируемый контроллер прерываний
  32. Другая сторона: цифровое аудио
  33. 1 битный ЦАП
  34. Время экзамена.
  35. Можете ли вы угадать значения smpl1,smpl2 и smpl3 ?
  36. Линукc, а вот и мы !
  37. Символьные устройства в Линукс
  38. Регистрация нашего драйвера
  39. К рабочему драйверу устройства
  40. Взглянем на myhandler()
  41. Последний пункт.
  42. Cherry George Mathew

PC speaker (Русский)

Хотим мы этого или нет, компьютер часто издает звуковые сигналы и другие звуки. Они происходят из различных источников и, как правило, вы можете настроить условие или время для их срабатывания. Для случаев, когда нет звуковой карты или динамиков, и требуется простое аудио оповещение, смотрите раздел #Beep.

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

Contents

Отключение PC Speaker

Отключение конкретного источника звука, в то время, когда остальные продолжают работать, возможно только в том случае, если мы может определить какая часть окружения сгенерировала конкретный звук. Это позволяет выборочно настраивать звуки. Пожалуйста, размещайте свои примеры настроек и конфигураций, которые могут оказаться полезными для других пользователей.

Глобально

PC speaker может быть отключен выгрузкой модуля ядра pcspkr :

Помещение в черный список модуля pcspkr предотвратит его загрузку udev при загрузке системы:

Размещение в черном списке в командной строке ядра — еще один способ добиться похожего эффекта. Просто добавьте modprobe.blacklist=pcspkr к вашей строке начальной загрузки ядра.

You can add this command to a startup file such as /etc/xprofile to make it permanent. See xprofile for more information.

Терминал

Вы можете добавить эту команду в /etc/profile или в отдельный файл вроде /etc/profile.d/disable-beep.sh :

Другой способ — это раскомментировать или добавить строку в /etc/inputrc или

Постраничный вывод утилитой Less

Для отключения PC speaker при использовании утилиты less , вы можете запустить её с параметром less -q , чтобы заглушить PC speaker по достижении конца постраничного вывода, или less -Q чтобы отключить повсеместно. Для получения справки, выполните man -P «less -Q» или настройте переменные окружения $MANPAGER или $PAGER .

Также, вы можете добавить следующие строки в ваш .bashrc:

Для большинства звуковых карт PC speaker отображается как канал ALSA, и может называться как PC Speaker, PC Beep, или Beep. Чтобы заглушить динамик, воспользуйтесь alsamixer или amixer.

Для включения звука обратитесь к странице руководства Advanced Linux Sound Architecture#Unmuting the channels.

GNOME

При использовании GSettings:

Cinnamon

В Cinnamon вероятно используется звук «падающей капли». Для его отключения, измените в dconf:

Добавьте следующую строку в

Добавьте такую же строку в секцию [Settings] файла $XDG_CONFIG_HOME/gtk-3.0/settings.ini :

Beep — это улучшенная программа для подачи звукового сигнала посредством PC speaker. Она может оказаться востребована в ситуациях, когда звуковая карта отсутствует или нет доступных динамиков, но требуется простое звуковое уведомление.

Установка

Возможно, вам потребуется включить звук канала PC speaker в ALSA.

Доступ для обычных (non-root) пользователей

По умолчанию, beep не будет работать, если запущена не с правами суперпользователя. Другие пользователи могут использовать ее при помощи sudo. Для передачи группе users возможности вызывать sudo beep без пароля (например, для использования в скриптах), следует отредактировать /etc/sudoers :

или выдать права только одному пользователю:

Также можно настроить бит закрепления в памяти /usr/bin/beep :

Обратите внимание, что при этом любой сможет выполнять /usr/bin/beep без прав суперпользователя. Изменение также создаст разность между локальной копией и пакетом, о чем будет сообщено в pacman -Qkk .

Полезные советы

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

Источник

PC speaker

The computer often seems to make beep noises or other sounds at various times, whether we want them or not. They come from various sources, and as such, you may be able to configure if or when they occur. For situations where no sound card or speakers are available and a simple audio notification is desired, see #Beep.

Sounds from the computer can be heard from the built-in case speaker, the speakers, or headphones which are plugged into the soundcard (in which case the noise may be unexpectedly loud).

Contents

Disable PC Speaker

Turning off a particular instance of a sound, while leaving the others operational, is possible if and only if one can identify which portion of the environment generates the particular sound. This allows customizing the selection of sounds. Please feel free to add any configurations and settings to this wiki page that may be useful for other users.

Globally

The PC speaker can be disabled by unloading the pcspkr kernel module:

Blacklisting the pcspkr module will prevent udev from loading it at boot. Create the file:

Blacklisting it on the kernel command line is yet another way. Simply add modprobe.blacklist=pcspkr to your bootloader’s kernel line.

Console

You can add this command in /etc/profile or a dedicated file like /etc/profile.d/disable-beep.sh :

Another way is to uncomment or add this line in /etc/inputrc or

Less pager

To disable PC speaker in less pager, you can launch it with less -q to mute PC speaker for end of line events or less -Q to mute it altogether. For man pages, launch man -P «less -Q» or set the $MANPAGER or $PAGER environment variables.

Alternatively, you can add these lines to your

You can add this command to a startup file such as /etc/xprofile to make it permanent. See xprofile for more information.

For most sound cards the PC speaker is listed as an ALSA channel, named either PC Speaker, PC Beep, or Beep. To mute the speaker, either use alsamixer or amixer , for example:

GNOME

KDE Plasma

Bell notification settings can be modified in «System Settings»->»Accessibility Options»->»Bell».

Cinnamon

Cinnamon seems to play a «water drop» sound. To disable it, set in gsettings(1) :

Append this line to

Add the same line to the [Settings] section of $XDG_CONFIG_HOME/gtk-3.0/settings.ini :

PulseAudio

Play a sound instead of a PC speaker beep using PulseAudio.

A user can create a short audible tone when logged in to a virtual console. See Wikipedia:bell character#usage for the details.

Beep is an advanced PC speaker beeping program. It is useful for situations where no sound card and/or speakers are available, and simple audio notification is desired.

Installation

You may also need to unmute the PC speaker in ALSA.

Run as non-root user

beep uses /dev/input/by-path/platform-pcspkr-event-spkr to control the PC speaker. To access it as a non-root user, one has to set the proper permissions. Create /etc/udev/rules.d/70-pcspkr-beep.rules and add the following rule:

That will allow any user, who is logged into the currently active virtual console session, to use the PC speaker.

Alternatively, a new user group may be created (e.g. beep ) with the corresponding rule to set the right permissions on the device file:

With that solution any user in the beep group will be able to control the speaker.

To force reloading rules and device file to apply new user permission without a reboot, execute:

Tips and Tricks

While many people are happy with the traditional beep sound, some may like to change its properties a bit. The following example plays slighly higher and shorter sound and repeats it two times.

Источник

Персональный блог Толика Панкова

Стихи, рассказы, философия, IT, политика, панкизм, раздолбайство и болтовня.

После прочтения 126 заголовков, созданных генератором новостей, Николя Саркози объявил национал-предателем высокопоставленного заокеанского покровителя майора Евсюкова

PC-speaker в Linux, или как сделать beep из консоли встроенным динамиком ПК

Еще со времен DOS можно было свистеть, гудеть и пикать встроенным динамиком компьютера, и даже симфонии играть. Сейчас это особо не нужно, ибо везде звуковые карты, динамики и прочая мультимедия. Но иногда PC-speaker нужная и полезная вещь, способная сигнализировать о чем либо, например, о разрыве соединения с Интернетом на домашнем сервере, к которому не подключен монитор, или о том, что торрент докачался. Да и вообще, способов, как можно применить спикер — множество. Даже симфонии можно играть.

Зачастую, PC-speaker в линуксе отключен, точнее, не загружен модуль ядра, который им управляет. Обычно это модуль pcspkr , хотя, в некоторых источниках написано, что может быть и другой модуль snd-pcsp. У меня оказался первый.
Проверить, загружен ли соответствующий модуль ядра можно командами
lsmod |grep pcspkr и lsmod |grep snd-pcsp соответственно.
Если команда ничего не выдала, то модуль не загружен.
Если выдала что-то похожее, значит, модуль загружен:

Читайте также:  Чем windows server 2012 отличается от windows server 2012 r2

Если модуль не загружен, нужно попробовать его загрузить:

modprobe pcspkr
или
modprobe snd-pcsp

Если команда не выдала ошибки, модуль загружен. Можно проверить с помощью команды lsmod . Если случилась ошибка, то печально. Модуль, скорее всего, придется собирать. Ну, или не так печально, а даже наоборот — модуль встроен в ядро, и PC-speaker по умолчанию включен. Попробуйте простой beep.

Для простого beep достаточно отправить на консоль символ с кодом 007, ASCII-символ BEL

Способ может не сработать из SSH-терминала, либо из терминала X. Терминал SSH «булькнет» не на удаленном компьютере, а на локальном, а X-server может перенаправить beep на колонки, вместо PC-speaker’a

Простые звуки и даже целые мелодии можно играть на спикере утилитой beep .
На рабочей машине она уже была в комплекте ОС, на Ubuntu ее можно установить командой apt-get install beep , а в Slackware она ставится через Sbopkg
Проект имеется на Github, можно собрать и из исходников

Без параметров издаст стандартный beep

beep -f 500 -l 1000

Выдаст звук частотой 500 Гц, продолжительностью 1 секунду (1000 миллисекунд)

Пример скрипта, играющего тему Die Gedanken Sind Frei из ролика в начале заметки.

Источник

Linux устройство pc speaker

Иногда я удивляюсь, как просто изобрести колесо еще раз, и потом болтать о том, скольких трудов это стоило вначале. Эта статья для тех симпатизирующих мне «крепких орешков» :), которые считают, что удовольствие от того, что ты сделал что-то самостоятельно, более важно, чем быть пионером, первым человеком на земле, ступившем не луну .

Я решил заставить PC speaker извергать рок музыку.
(Speaker — это та маленькая невидимая штучка в корпусе компьютера, которая пищит у вас под кожей, когда вы становитесь непослушным.) Я хотел заставить её играть настоящую музыку. Мне не хотелось суетиться и писать весь код с нуля, для декодирования mp3, и т.д. и т.п. Поэтому я поленился и решил немного поиграть с cамым задокументированным, самым изощренным из созданных когда-либо ядер операционных систем — Линукс 😉

Что вы делаете, когда вы впервые в городе и хотите попасть из точки ‘a’ в точку ‘b’? Я делаю глубокий вдох и начинаю свою прогулку по деловому центру города. Я начинаю собирать информацию и открывать места. Идиотизм? Просто попробуйте этот метод в городе ядра Линукс. Это головоломка кода, головокружительный лабиринт перекрестно связанных директорий и makefile’ов. Когда я начинал, я знал что это будет длительный проект. Но у меня был ‘посох’ DOS и ‘жезл’ Peter Norton’s guide to the IBM PC and Compatibles со мной, чтобы придать мне немного храбрости. Поэтому я пошел большим шагом, держа нос по ветру, готовый принять худших ‘демонов’ ;).

Патчи с драйверами для PC-speaker доступны для загрузки по следующим адресам, ftp://ftp.uk.linux.org/pub/people/dwmw2/pcsp/ (Автор Michael Beck, поддержка David Woodhouse см. http://linux-patches.rock-projects.com/v2.2-d/pcsp.html ) Я понимаю, нужно перекомпилировать ядро, чтобы они заработали. Когда я начинал, я был готов свалять дурака и получить быстрые результаты. В конце концов это все игра, не так ли ? 😉 Вот почему вы обнаружите ассемблерные фрагменты в коде. В любом случае, вот как это работает .

PC speaker: общие сведения

Внутренний динамик привязан к буфферизированному выводу микросхемы таймера 8254 на всех PC. Затем вывод таймера 8254 запирается через встроенный системный периферийный чип, через порт 61h.

PIC расшифровывается как программируемый контроллер прерываний

Базовая частота 8254 — 1193180Hz, что, по совпадению, составляет 1/4 стандартной частоты NTSC. Счетчики имеют значение делителей, которые, грубо говоря, используются для деления базовой частоты. Поэтому вывод канала 0 будет иметь частоту 1193180Hz если counter0=1, 596590Hz если counter0=2 и так далее. Поэтому сounter0=0 => частота приблизительно 18.2Hz, что точно соответствуют частоте с которой PIC прерывает процессор. В DOS, PIC программировался чтобы вызывать Interrupt Service Routine (процедуру обработки прерывания) (ISR), по вектору 8.

На самом деле это значит, что значение counter0 будет определять частоту с которой вызывается ISR таймера (Вектор 8 в DOS). Изменение значения counter0, изменяет частоту с которой вызывается ISR таймера. Поэтому если один и тот-же человек написал код для ISR и для программирования counter 0, чипа таймера 8254, то он может заставить его ISR вызываться с заданной частотой.

Все это ведет в другую сторону.

Другая сторона: цифровое аудио

Когда вы слышите звук, вы знаете, что нечто рядом с вами вибрирует. Если это что-то — динамик спикера, вы знаете, что есть электрический сигнал, управляющий им. Поэтому мы всегда можем взять генератор сигнала за шкирку, если мы хотим прекратить шум. Если нам нужно аудио, нам нужны вибрации, или переменное напряжение. И мы знает что слово «цифровой» предполагает цифры, 1 и 0. Как нам сложить это все вместе и получить цифровое аудио?

Давайте представим, что мы хотим, чтобы продолжительный гул будил нас ото сна по утрам. Пожелайте удачи тому человека, который попробует продать такую поделку мне 🙂 ! Нам нужна продолжительная синусоидальная волна.

Цифры представляют насколько громким становиться звук в каждый момент. Вы невольно выполняете здесь DSP (цифровую обработку сигнала). DSP — это самая большая головная боль второго года обучения для большинства студентов обучающихся Electrical Engineering. (Я один из них. Примите мои искренные соболезнования.) Поэтому я лучше упомяну, что вы сейчас смотрите на образцы. Эти значения — все что вам нужно, чтобы воссоздать нужную нам волну. Повторяйте это, и вы получите продолжительную волну. Итак если мы пробежимся через цифры начиная с 1 через 7 через 0 через -1 через -7 через -1 к 0, в течении секунды, мы получим очень приблизительную синусоидальную волну с частотой 1Гц. (Помните, Герцы это количество циклов в секунду). Поняли механику работы? Хотите синусоидальную волну с более плавными изгибами? Просто увеличьте число ‘образцов’, которые вы берете за секунду. У нас взято 14. Что если бы их было 44000? Это частота с которой CD проигрыватель изрыгает числа в свой DAC. DAC — это ЦАП (Цифро-Аналоговый Преобразователь), небольшое устройство которое преобразует 1 и 0, образующие двоичные числа, о которых мы ведем беседу, в настоящее аналоговое, изменяющее во времени напряжение. Наша небольшая техника кодирования, называется импульсной модуляцией кода. Есть разные пути кодирования импульсов, поэтому у нас есть PCM, ADPCM и т.д. Форма волны приведенная выше может быть описана как «4 бита, со знаком, моно PCM с частотой сэмплирования 14Гц».

1 битный ЦАП

Итак вы спрашиваете меня, как это все используется, когда мы говорим о PC speaker’е? Как насчет специального ISR таймера, которые заставил бы динамик speaker’а вибрировать с предустановленной частотой, так, чтобы все, что программисту ISR оставалось сделать — это заставить динамик двигаться с определенной амплитудой ( расстояние от нулевой линии) в соответствии со значением образца, которое он получает из цифровых данных, например с CDROM. Это значит, что вы можете настроить таймер ISR на 44000Гц и вот она — музыка CD качества — смотрит на нас! Совершенная логика, если у вас есть ЦАП, чтобы преобразовывать каждый образец в соответствующее аналоговое напряжение. На самом деле ЦАП парралельного порта делает именно это. Просто оснастите его лесенкой резисторов R — 2R и приделайте конденсатор к выходу, скормите это любому усилителю, даже микрофонный вход подойдет, и вуаля, у вас есть цифровая музыка!

К сожалению, все не так просто с PC speaker. Все потому-что PC speaker подсоединен не к ЦАП, а к чипу таймера.

У нас есть две дискретные величины, с которыми мы можем работать: Одна +5В, другая 0В и ничего между ними. Как же нам получить Аналоговую волну? О человек, зачем ты просишь о невозможном? Спросите инженеров из IBM, которые разработали первые материнские платы для XT!

Но у нас есть очень тонкое и хитрое решение. В технических терминах это означает: 1 битный DAC, Колебания и тому подобное.

Это нечто достаточно простое и легкое в реализации, и когда-то в конце концов оно было обречено на свое воплощение в жизнь. Я сомневаюсь, что старый XT-шный бедолага из IBM, когда либо мечтал о 1,5 Ггц Пентиумах, когда он устанавливал свой 8086 на материнской плате в первый раз.

Идея состоит в том, чтобы двигать динамик PC speaker’а рывками, когда мы не можем просто перевести его на отметку постепенно. Напомню вам, на 22Кгц динамик это здоровенный ленивый парень, он неохотно двигается на установленную отметку. На полпути туда, беря передышку, так, что если он перегружен и динамик зашел слишком далеко, у него появляется время, чтобы вернуться назад. Нечто вроде анти-блокировочных тормозов в автомобилях. Когда вы наполовину вжимаете педаль тормоза, механизм начинает попеременно включать и выключать тормоза. Когда вы выжимаете педаль, тормозные колодки на самом деле не прижимаются к колесному диску, они бьются об него в яростном темпе. Так что колесо не блокируется. Аналогично, чем быстрее вы бьете динамик пяти-вольтовым импульсом, тем дальше он двигается от центральное линии. Бинго! Изменяйте частоту импульсов в соответствии с нужной амплитудой. Я назвал DOS версию fm.com, просто чтобы напомнить себе что идея на самом деле проста.

Читайте также:  Mvvm для windows forms

Теперь отправляйтесь назад к первой иллюстрации и посмотрите на счетчик 2, чипа 8254. Куда он ведет? К PC speaker, конечно. Теперь все, что нам нужно сделать, чтобы получить НАСТОЯЩИЙ звук, — это сбросить отмаштабированное значение (помните 1 амплитуды в PCM). Мы делаем это из нашего хэка ISR таймера. Посмотрите на функцию myhandler() в myaudio.h.

Время экзамена.


Можете ли вы угадать значения smpl1,smpl2 и smpl3 ?


Линукc, а вот и мы !

Ядро Линукс — это потрясающий пример программирования, с той точки зрения, что он был организован настолько хорошо, что человек с небольшими знаниями или вообще без знаний ассемблера, может написать большой фрагмент кода ядра (на самом деле около 99% [поспорим :)] написано на «c»). Оно также спроектировано таким образом, что драйвера устройств получают предопределенное окружение и элегантный, исчерпывающий программный интерфейс для написания кода.

Код ядра очень портабелен, т.е. он может быть скомпилирован на разнообразных машинах (процессорах вроде i86, alpha, sparc). Я думаю, что это правильная логика, писать шаблоны кода, которые могут быть тщательно проработаны и приспособлены для конкретного «железа». Говоря по Английски :), я могу лучше проиллюстрировать этот принцип при помощи примера. Предположим, что вы хотите опубликовать свою докторскую диссертацию о том, как стирать бельё, используя вашу марку стиральной машины. Вы напишите последовательность шагов, начиная с:

1) Вставьте шнур питания в настенную розетку и включите питание

n) Наконец, выньте вашу одежду из кучи и вывесите на веревочке.

Последовательность от 1 до n может быть различна, в зависимости от того, была ли ваша стиральная машина полу- или полностью автоматической, обладала ли загрузкой сверху или сбоку (попробуйте шаг ‘n’ для машины с боковой загрузкой, и пришлите мне e-mail об этом) и других переменных. Инструкции в вашем очерке будут подходить для одной стиральной машины, но что если вы свободный писатель пользовательских руководств и вам нужно написать руководство для тысячи марок?

Возьмем случай с интерфейсом устройства /dev/dsp, интерфейс по умолчанию для PCM (импульсно модулированный код) и закодированного PCM звука. Hannu Savolainen сконструировал большую часть интерфейса, а Alan Cox сделал примечательные дополнения. Но эти разработчики — конечно правильно — не оставили места для одного маленького устройства, называемого PC-speaker, в пользу AWE 64 и тому подобных карт. Они решили что все DSP устройства имеют как минимум поддержку DMA (Direct Memory Access это технология, при помощи которой «умные» периферийные чипы берут на себя заботу о чтении/записи данных в RAM, без вовлечения процессора), или буферы на карте, если не сопроцессоры (т.е. процессоры на плате). Поэтому они поместили код DMA регистрации в качестве обязательной части OSS API. OSS API имеет два уровня экспортированных функций: одни экспортируемые soundcore.o и другой набор, экспортируемый sound.o

sound.o размещается поверх soundcore.o и использует его экспортированные функции, как и любой другой драйвер устройства. Он предоставляет простой интерфейс для портабельных драйверов устройств и поддерживает «продвинутые» функции вроде DMA доступа. (Современные звуковые карты поддерживают как минимум DMA)

Вот где начинается «взлом». Мы должны обойти стандартный интерфейс OSS, и использовать интерфейс soundcore напрямую. Это означает, что пришло время для другого технического разговора — символьные устройства в Линукс.

Символьные устройства в Линукс

В Линукс, два основных типа устройств: блочные и символьные. (Мы игнорируем сетевые устройства, т.к. они не являются настоящими «устройствами», скорее интерфейсами.)

Блочные устройства подразумевают наличие некоторых определенных характеристик, таких как чтение и запись блоками, буферизация, разбиение на разделы и т.д. Жесткий диск — это отличный пример блочного устройства. Приложение обычно обращается к жесткому диску через драйвер файловой системы. Вот почему в Unix вы монтируете накопители и не обращаетесь к ним сектор-за-сектором.

Символьные устройства предназначены для по-байтного чтения и записи (например последовательный порт), но прозрачно буфферизируются, чтобы улучшить пропускную способность системы. Приложение обращается к ним при помощи обычных файловых операций с соответствующими нодами. Ноды устройств это специальные «файлы», к которым можно обращаться через обычное дерево каталогов. Если вы хотите писать в звуковое устройство, по умолчанию, /dev/dsp это нода устройства используемая для этого. Заметьте, что нода любого устройства, которая указывает на соответствующий номер устройства, зарегистрированный драйвером, может использоваться для доступа к этому драйверу. Например, нода /dev/dsp привязана к номеру устройства 14/3. (попробуйте: file /dev/dsp; на вашей системе). Вы с равным успехом можете обращаться к нему через /dev/mynode, если /dev/mynode указывает на 14/3. Проверьте man страницы mknod на предмет точного синтаксиса команды.

Теперь, если у вас есть .wav файл специфичного формата, скажем 16-бит, стерео, чистый pcm, чтобы проиграть его на вашем системном звуковом устройстве, вы можете открыть ноду /dev/dsp, используя системный вызов open, и открыть ваш .wav файл, считать блок данных из .wav файла, и записать его в ноду /dev/dsp, используя системные вызовы read и write соответственно. АГА! И угадайте — какая программа способная сделать это уже доступна? Наша любимая cp! Поэтому в следующий раз попробуйте, cp -f fart.wav /dev/dsp. И расскажите мне, как это звучало. Бьюсь об заклад, что, если вы не очень удачливы, вы не получите правильный звук, даже если вы играете Celine Dione. Это происходит потому-что звуковому драйверу нужно сказать, какой формат необработанных данных он получает. Чаще всего, вы будете пытаться проигрывать 16-битные стерео файлы с частотой 44khz на 8-битном моно 8Кгц драйвере. Это все равно что пытаться проигрывать LP диск на неправильной частоте вращения.

Системный вызов ioctl (input/output control — управление вводом/выводом) используется на /dev/dsp, чтобы говорить с драйвером устройством. К сожалению, конкретный синтаксис вызова ioctl оставлен на усмотрение автора драйвера устройства. Это похоже на хаос, творящийся на рынке приложений для DOS. К счастью у нас есть несколько распознаваемых соглашений в Линукс, самые популярные из которых это OSS или Open Sound System (Открытая Звуковая система). Это интерфейс встроенный в Линукс Sovolainen & Co. Итак у нас есть XMMS plug-in’ы для OSS на стороне приложений, и множество драйверов на стороне ядра.

Когда приложение делает «вызов» open, оно на самом деле вызывает что-то. Это что-то — это процедура ядра (помните, open это системный вызов). Ядро сконструировано так, чтобы передавать вызов к соответствующему драйверу устройства. Восхитительно прекрасная особенность ядра Линукс — это то, что вы можете приказать ядру вызывать вашу функцию, для конкретного номера устройства. Эта называется регистрацией обработчика устройства, и это вызов в режиме ядра, т.е., вы не можете писать приложения, которые делают эти вызовы, и могут быть запущены с терминала. Аналогично вы можете «играть» с ядром, и передавать вызовы пользователя последующим функциям, если вы сконструируете и экспортируете свои собственные функции регистрации. Это точно то, что делает soundcore.o, через register_sound_dsp(). (Хорошо, орошо , подождите, спросите меня. Мы скоро «нырнем» в звуковые модули OSS. Просто надо убедиться, что в бассейне есть вода!). Вы используете для этого insmod, и пишите специальную программу называемую модулем ядра, которую insmod может загрузить в пространство ядра и присоединить к системным вызовам ядра. Главное различие между системными вызовами и вызовами в режиме ядра, это то что системные вызовы должны соответствовать общепринятым соглашениям, если они должны распознаваться как часть Unix. (Помните «what is Linux» FAQ?) Говоря по другому, ядро — это Линукс. Итак, нам нужно следовать лишь соглашениям ядра Линукс при программировании ядра, и напомню вам, от 9 до дюжины соглашений ядра Линукс меняется с каждым релизом. Вот почему у нас есть «pre-x.xx.xx version compile only» предупреждения со многими релизами двоичных модулей. По минимуму, нам нужно иметь функции read и write, не считая open и close. Ядро Линукс определяет функцию, называемую init_module и другую называемую cleanup_module, которые вызываются ядром при подключении и изъятии нашего модуля. (Нечто вроде main() в пространстве пользователя). Другими словами, когда мы пишем функцию init_module, мы подразумеваем, что имеем полный контроль над системными портами, памятью и т.д. и что мы можем вызывать все доступные функции ядра. Другая интересная вещь заключается в том, что любая функция ядра или модуля может быть экспортирована в таблицу символов ядра (смотри /proc/ksysm на предмет списка), так, что её можно вызвать из любой другой функции ядра или модуля. Другими словами, исполнимый файл ядра, /boot/vmlinuz, в оригинально был C программой запускаемой с main(), также как и любая другая программа написанная вами или мной на C. Не считая того, что скобочки были заполнены весьма талантливым программистом по имени Линус Торвальдс.

Читайте также:  Windows не может проверить лицензию

Регистрация нашего драйвера

Самая критичная часть всей дискуссии — это, конечно, сам код. Регистрация драйвера производится при помощи функции register_sound_dsp, экспортированной модулем soundcore.o, который, как я объяснял раньше, часть стандартного дистрибутива OSS. Все, что она делает, это пропускает вызов open от приложения пользователя. Большая часть кода интуитивно-понятна. Ассемблер GNU (оригинальный формат ассемблера AT&T) имеет дело с «прицеплением» обработчика прерывания таймера. Функции setvect и getvect работают в целом так же, как они делают это в DOS. (ОК давайте, вперед, скажите ХЭЙ — я знаю что ты врешь. Я не был рожден в Bell labs, знаете-ли 🙂

К рабочему драйверу устройства

Для нас основная работа заключается в том, чтобы получить работающий драйвер устройства, который может получить доступ к PC speaker через порт таймера 8254, и проделывать фокусы, которые будут копировать звуковые данные приложения в PC speaker, байт за байтом.

OSS создает ноду устройства называемую /dev/dsp для нас. Наш драйвер называемый myaudio.o может быть загружен в действующее ядро при помощи insmod myaudio.o, и удален rmmod myaudio. /dev/dsp указывает на наш драйвер, после insmod.

Давайте взглянем на структуру программы. Нам нужно сделать следующее:

1) Зарегистрировать наше поддельное dsp устройство 2) Прицепиться к прерыванию таймера и установить прерывание на нужную частоту сэмплирования. 3) Напечатать сообщение, которое говорит «Фью»! Ядро скажет вам, если что-то пошло не так. Во многих случаях, оно перезагрузит для вас систему.

Когда драйвер выгружен, нам нужно восстановить систему к её предыдущему состоянию, выполнив следующие шаги:

4) «Отцепить» вектор прерывания таймера и сбросить прерывание на старую частоту. 5) Отменить регистрацию устройства dsp 6) Напечатать сообщение об успехе.

Взглянем на myhandler()

Код примера находиться в двух файлах называемых myaudio.c и myaudio.h. myaudio.c содержит функции регистрации устройства, которые делают всё вышеописанное. myaudio.h содержит очень важную функцию называемую ISR ( Interrupt Service Routine — Процедура обслуживания прерывания). Она называется myhandler(). Я думаю, что шаги описанные выше, лучше объясняются путем чтения кода myaudio.c. Обратите свое внимание на myaudio.h, в частности на myhandler().

Шаг 2 описанный выше, говорит: «прицепиться к вектору прерывания таймера». Это означает, что ISR настраивается так, чтобы вызываться с нужной нам частотой. Это означает, что когда я пишу код в ISR, я могу быть уверен в следующем: a) Следующие данные приложения пользователя, если они доступны, должны быть получены. b) Их нужно преобразовать в значение счетчика (counter) 2 8254 ( подробно обсужденного выше). c) Это значение счетчика должно быть сброшено в регистр счетчика 2, 8254: т.е. задержка для PC-speaker устанавливается в соответствии с значение полученных данных и d) Системный планировщик еще не был вызван ! Решить вызывать-ли его.

Шаг d) требует отступления:

Если вы читали код setvect() в myaudio.c, вы должны были обнаружить, что setvect использует несколько уловок, чтобы поместить myhandler в системную таблицу векторов. Это специфично для Intel 386+. В режиме реальных адресов 8086, все что нужно сделать чтобы перенаправить указатель ISR, это сохранить соответствующее значение в таблице векторов прерываний (IVT), которая начинается с адреса 0000:0000 и хранит 4х байтовые значения. (Т.к. полный длинный указатель в 8086 длиной 32 бита cs:ip). Другими словами, для прерывания 8, которое является установленным BIOS по умолчанию для IRQ 7 PIC’а (программируемый контроллер прерываний), просто измените значение указателя по адресу 0000:0020 на полный адрес myhandler(). Здесь все немного усложняется. В защищенном режиме i386+, в котором работает ядро Линукс, процессора, IVT называется IDT, или Таблица Дескрипторов Прерываний. Более менее полное описание IDT заняло-бы весь HOWTO (врет, все не так страшно 🙂 Прим. переводчика.), но я, подразумевая то, что вы знаете о защищенном режиме i386, если это вам это нужно, и оставляю все жуткие детали для вашего докторской диссертации. Что нам действительно нужно знать, это то, что указатель на myhandler разбросан по 8-байтной области. Эта информация собирается вместе при помощи некоторых хитрых инструкций ассемблера GNU, чтобы создать оригинальный ISR указатель, который на самом деле указывает на системный ПЛАНИРОВЩИК (специальная программная процедура в любой многозадачной операционной системе), указывающий на myhandler(). В задачи ПЛАНИРОВЩИКА входит отбирать управление у одной программы, когда истечет её кусочек времени, и передавать его следующей. Это называется pre-emptive многозадачность. В Линукс, временной фрагмент выделяемый процессу равен 10 миллисекундам. Можете-ли вы угадать частоту с которой вызывается ISR таймера, установленное по умолчанию? Это значение называется HZ, в ядре Линукс.

Весь фокус в том, что оригинальный ISR (планировщик) должен вызываться с частотой 100Hz, но ISR требует вызова на частоте сэмплирования, обычно 22Кгц. И если мы пренебрежем вызовом оригинального ISR, вся система развалится к чертям собачьим :). Но есть простое решение. Если вы знаете частоту, с которой вы вызываетесь и с которой должен вызываться оригинальный ISR, просто вызывайте его 1 раз, из нескольких. Другими словами: на 22Кгц, увеличивайте значение счетчика на 1 при каждом вызове и когда счетчик достигнет 220, вызывайте старый ISR, иначе шлите EOI (Конец прерывания) PIC. Таким образом старый ISR будет вызываться ровно на 100Гц! Черная Магия ! Если вы забудете компенсацию для частоты, то будет очень интересно наблюдать, что произойдет. Просто попробуйте. На моей системе, минутная стрелка xclock вращалась как колесо рулетки!

Если вы взгляните на иллюстрацию выше, которая показывает, как прерывание таймера 8254 прицепляется к PIC, вы заметите, что когда 8254 хочет прерваться, он говорит PIC, через линию IRQ номер 7, (которая на самом деле просто кусок медного провода встроенного в материнскую плату). В наши дни, конечно, множество старых чипов интегрировано в один, так что можете не искать провод обозначенный IRQ7 на вашей плате! PIC решает как и когда прерывать процессор. Есть стандартный метод распределения прерываний, он называется определением приоритета прерывания ( prioritization), который находится целиком в ведении PIC. В Линукс, PIC перепрограммируется, чтобы вызывать вектор 20, для ISR таймера (IRQ 7) как для вектора 8 в BIOS и DOS. После каждого прерывания, соответствующая ISR должна делать EOI, которое на самом деле означает outportb(0x20,0x20). Поэтому нужно быть осторожным, чтобы убедиться, что не будет послано двойное EOT, одно от вас, и одно от оригинального ISR, который не знает о вас.

Последний пункт.

Я полагаю, что это все, но перед тем как я уйду с чувством полного удовлетворения, что я «запихал Латынь в тысячу глоток», я хочу прояснить несколько вещей о примере, который я сделал в моем myaudio.x. Линукс имеет формальный метод объявления прерываний для драйверов устройств. Проблема в том, что к тому времени, как загружается модуль, планировщик уже объявил прерывание таймера. Поэтому нам нужно пойти на небольшой взлом и украсть его у планировщика. Вот почему мы обсуждали IDT и все прочее. Интерфейс OSS, который я написал в коде, это pre-alpha. На самом деле, вы можете запускать приложения вроде mpg123, play и даже xmms и вы получите возможность взглянуть на синхронизацию событий в Мульти-Мульти Операционных системах, если вы добавите -D SPKDBG в опции компилятора в myaudio.mak. «-D SPKDBG» включает отладочные сообщения. Однако будьте осторожны, ваша машина может не справиться с огромным количеством данных поступающих в логи. Поэтому делайте это только если вы действительно знаете, что делаете. Я поставил доработку OSS в список TODO. Можете завершить её.

Сделайте следующее, чтобы использовать наш драйвер: Как пользователь root, перейдите в директорию куды вы скопировали исходные файлы: myaudio.c, myaudio.h, и myaudio.mak. Запустите: подразумевается, что вы имеете стандартный дистрибутив OSS на вашей машине. (Путь в /usr/src/linux/drivers/sound. Проверьте это.)

Теперь драйвер активен. Проверьте его при помощи:

Поищите myaudio на верху списка. mpg123, play и xmms теперь должны работать как обычно.

Если не одно из выше указанных приложений не работает, то можно слушать MP3 музыку при помощи следующей команды:

Наслаждайтесь. Примечание: Все эти операции необходимо проделывать как пользователь root. Поэтому я предполагаю что вы используете вашу собственную машину, и готовы испортить любую её часть, возможно навсегда. Я не могу взять на себя какую-либо ответсвенность за то что случится с вашей системой из-за моего кода, поэтому я настаиваю, чтобы вы пробовали его только на ваш страх и риск. Я проверял мой пример на RedHat 7.1, запущенной на Celeron 366/64МБ RAM. Действительно заинтересованным людям, которые не хотят рисковать своей машиной, я рекомендую использовать патчи от Michael Beck, но тогда вы не читали бы этого, не так-ли?

Если ваш ответ был таков то вы прошли тест. Теперь можете наниматься в Creative labs 😉 Листинг программы:

  • myaudio.h
  • myaudio.c
  • Makefile

Cherry George Mathew

Владимир Меренков | Александр Михайлов | Иван Песин | Сергей Скороходов | Алексей Саввин | Павел Ступин | Роман Шумихин |

Со всеми предложениями, идеями и комментариями обращайтесь на [email protected]

Источник

Оцените статью