Kevin's Linux kernel beep module

What is this?

In this modern day and age, it makes no sense for an operating system kernel to be making beeping sounds when alerts occur. In Linux, unfortunately, the mechanism for making beeps is coded deep in the kernel, in the implementation of the virtual console driver. This has a number of problems.

beep.o is a loadable module that puts beep support into the process level, and out of the kernel. It allows an application (or daemon) to determine when the kernel has requested a beep, and handle it in whatever manner is desired. Of course, one way of handling it might be simply to ignore it. Another might be to convert the beep into an audio operation on the soundcard.

Package contents

This package contains three things: (1) this file, which contains instructions on how to make the small kernel patch you need; (2) the source and Makefile for the loadable module; (3) a sample shell script that plays `boing' sounds when a beep is requested.

Design choices

This is not the only beep patch available but it has, I believe, some important advantages over other beep solutions.

Installation and configuration

Check whether your kernel is configured to export the symbol kd_mksound. For example:
cat /proc/ksyms | grep kd_mksound
It probably won't be (it's not the default), but it's worth checking because you won't need to recompile the kernel if the symbol is exported.

If you don't find the symbol, you'll need to reconfigure and recompile the kernel. This isn't the place to explain how to recompile a kernel. The required modifications are very simple: just add the following lines to the end of /usr/src/linux/kernel/ksyms.c and rebuild and redeploy the kernel. You don't need to recompile any modules, just the kernel itself. I haven't supplied a formal kernel patch because the modification is so trivial.

extern void (*kd_mksound)(unsigned int count, unsigned int ticks);
EXPORT_SYMBOL(kd_mksound);
When you've rebooted, check that the symbol is exported, as described above. Give me a call if the procedure I have described does not cause the symbol to be exported. If you have module versioning turned on (this is the default), then you can expect a dummy version number to be appended to the real symbol, but it should still be recognizable.

Now compile and install the module. Unpack the archive into any handy directory, and check the directory settings at the top of the Makefile. These determine where the installed module, shell script and sample beep sound go. When you are satisfied with these, do

make clean
make
make install
The most important file created by this process is the loadable module itself, beep.o. You can load the module like this:
modprobe beep
If this is successful then you should find that the ordinary console beep has disappeared. This is because it's been seized by the beep module. If you get `unresolved symbol' messages from modprobe, please contact me.

In another console do

cat /proc/beep
This should simply wait until something happens that would normally cause a beep. The cat command will return immediately, when a beep is generated, outputting a pair of numbers. The first of these is the requested beep frequency in Hz, the second the requested beep duration in timer ticks (18 ticks to the second). It's up to you whether your user-level process honours these values or not. In practice, most software just asks the kernel to give a default beep, so they probably aren't important.

Where you go after this is up to you, to a large extent. This package contains a simple shell script `beepd' which uses the `play' utility to play a wav file when a beep occurs. If you don't have `play' or similar, the simplest was to get a beep sound is probably just to cat an audio file to /dev/dsp.

Technical stuff

beep.o works by redirecting the kernel symbol kd_mksound into a handler in the module. This redirection is made when the module is installed, and reversed when it is unloaded. Unloading therefore restores the normal beep. This symbol is not exported by default from the Linux kernel, so it necessary to add the EXPORT_SYMBOL line described above.

The function kd_mksound is defined in the Linux source in drivers/char/vt.c. If you look at this code you'll notice that it explicitly controls the speaker hardware.

The beep.o module creates a new /proc file called beep. When an application process reads this file it is simply put to sleep. I have been careful that the blocking consumes no CPU resources and allows the kernel idle task to continue to run. The application is woken up when anything -- in the kernel or elsewhere -- calls the function kd_mksound. Normally this will be because the application has made an ioctl request on the console driver to generate a beep. The module wakes up the process, whose read from /proc/beep then completes. The read contains the beep frequency and duration requested by the application or the kernel.

Author and legal

This kernel module was written by Kevin Boone and is (c)2002, distributed according to the GPL. You may do whatever you like with this code, provided that authorship continues to be acknowledged and source code remains available. Needless to say, there is no warranty of any kind, and you use this at your own risk. Please report bugs, etc., to kb@kevinboone.com.