The Linux Answering Machine

This page documents how I set up my home Linux box to work as an answering machine. This document is mostly for my own use, but it might be helpful to others with a similar configuration. The relevant software/hardware configuration is

Install the RPMs

You need to install the following RPMs
  1. mgetty-1.1.28-3
  2. mgetty-voice-1.1.28-3
(latest versions as of this writing, but see section about Caller ID below). The answering machine is based on the voice functions of the vgetty program that comes with the mgetty-voice package.

Put vgetty on the serial port

Assuming that your voice modem is connected to /dev/ttyS0 and that your default runlevel is 5, you would add something like
# Run the answering machine in runlevels 3, 4 and 5
S0:345:respawn:/sbin/vgetty ttyS0
to /etc/inittab. You can run
# telinit q
to force init to re-read the inittab. If you're init default runlevel is 3, 4 or 5 (the usual case), then vgetty will be started on /dev/ttyS0 automatically on boot. Details are in the man page, inittab(5).

Recording a greeting

You can skip the "play back" steps in the following, although you probably shouldn't, just to be sure you know what your greeting will sound like. All the monkeying around with sampling rates that follows was made necessary by the limitations of my sound card, which would only play at certain fixed rates. YMMV.
  1. Record a greeting at 18939 samples/second
    $ sox -c 1 -r 18939 -t ossdsp /dev/dsp greeting.wav
  2. Play it back to hear what it sounds like
    $ sox greeting.wav -t ossdsp /dev/dsp
  3. Convert the greeting to pvf ("Portable Voice Format") and from 18939 samples/second to 9600 samples/second.
    $ wavtopvf greeting.wav | pvfspeed -s 9600 >greeting.pvf
  4. Now play that back, converting back to 9700 samples/second on the fly
    $ pvfspeed -s 9700 greeting.pvf | pvftowav | sox -t wav - -t ossdsp /dev/dsp
  5. Convert the greeting from .pvf to ZyXEL_1496 .rmd
    $ pvftormd ZyXEL_1496 2 greeting.pvf greeting.rmd
  6. Now play that back, converting back to 9700 samples/second on the fly
    $ rmdtopvf greeting.rmd | pvfspeed -s 9700 | pvftowav | sox -t wav - -t ossdsp /dev/dsp
  7. Copy the greeting to where vgetty will look for it
    # cp greeting.rmd /var/spool/voice/messages/standard.rmd

Play a message

At this point, you have a very bare-bones but functional answering machine. vgetty will answer your telephone after a few rings (default is three), play your greeting, and record the message in an .rmd file in the directory /var/spool/voice/incoming. You can play those messages with
rmdtopvf [message.rmd] | pvfspeed -s 9700 | pvftowav | sox -t wav - -t ossdsp /dev/dsp

Set up a message program

If a bare-bones answering machine was what you wanted, then you probably wouldn't be trying to make your computer function as an answering machine. The "message_program" parameter in the vgetty configuration file, /etc/mgetty+sendfax/voice.conf, gives you quite a bit more flexibility in how the messages are handled. The value you set for this parameter is the path to the program that you want executed when a message is received. This program will be invoked with three arguments, the first is the name of the .rmd file containing the recorded message, the next two are the caller's phone number and name determined from caller ID (more on this below).

Here's a shell script that will convert the .rmd file to an 8000 samples/second .wav file and email it to you at work



WAVFILE=`echo $MESSAGE | sed 's/.rmd$/.wav/'`

rmdtopvf $MESSAGE | pvfspeed -s 8000 | pvftowav >$WAVFILE

echo "Number: $CALLERID Name: $CALLNAME" | mutt -s "telephone message from $CALLNAME" -a $WAVFILE you@work

exit 0

If you put this into a file called /etc/mgetty+sendfax/ and a line that reads
message_program /etc/mgetty+sendfax/
in /etc/mgetty+sendfax/voice.conf, then telephone messages left for you at home will get emailed to you at work as .wav file attachments. Note that you must run an MTA (such as sendmail, qmail or postfix) on your home computer in order for this to work. Some MTAs are considered significant security risks.

Caller ID

It took me some time to figure out how to get caller ID to work. The problem boils down to this: certain configuration registers in the ZyXEL modem have to be set or else it just ignores the caller ID information that is sent by the telco (BTW, the telco won't even send this information if you don't subscribe to caller ID ...). Quoting from the ZyXEL U-1496 Series User's Manual, page 12-4: "S-register S40b2 is used to enable (1) or disable (0) the caller ID detection function. The default is disabled." You also have to set bit S42b2 to get the modem to automatically send the caller ID message without being queried.

As far as I could tell, vgetty was not setting this register and so the voice modem was ignoring the caller ID information sent by the telco. So I dug through the vgetty source code looking for where the modem was initialized, and finally hit pay dirt in the file mgetty-1.1.28/voice/libvoice/ZyXEL_1496.c, in a function called "ZyXEL_1496_init" (unsurprisingly). This function sets bits 3, 4, 5 and 6 of S-register 40 to enable distinctive ring detection, but does not set bit 2 to enable caller ID.

mgetty, a close cousin of vgetty, supports user-defined modem init strings via the "init-chat" parameter in /etc/mgetty+sendfax/mgetty.config file. Unfortunately, as far as I could determine vgetty has no corresponding facility. However, this is free software so it is possible to patch the source code and fix this small deficiency in what is otherwise a superlative piece of software.

So I added a couple of lines of code to that the ZyXEL modem initialization would turn on caller ID detection, and since version 1.1.25 (which was shipped with Red Hat Linux 7.1) was getting a bit out of rev, I decided that I would patch up version 1.1.28 instead. So I rolled some RPMs, which are available below (N.B., the binary RPMs are for two architectures, namely Alpha and i386. The Alpha binaries are a bit out of rev now, but I will be updating them soon, once I get my PWS-600au back up!):

Patched mgetty RPMs
Alpha Intel
mgetty mgetty-1.1.28-5.alpha.rpm mgetty-1.1.30-0.8.i386.rpm
mgetty-sendfax mgetty-sendfax-1.1.28-5.alpha.rpm mgetty-sendfax-1.1.30-0.8.i386.rpm
mgetty-viewfax mgetty-viewfax-1.1.28-5.alpha.rpm mgetty-viewfax-1.1.30-0.8.i386.rpm
mgetty-voice mgetty-voice-1.1.28-5.alpha.rpm mgetty-voice-1.1.30-0.8.i386.rpm

and the source RPM is here.

Will it work with other modems?

The trusty ol' ZyXEL is a great voice modem, but it's expensive (about US$250) and slow when used for dialout (as a practical matter they are limited to 14,400 bits per second, unless the opposite modem is also a ZyXEL, in which case they go up to 19,200). If you're not a modem freak like me, then you probably want something faster and cheaper.

The following table is a summary of some modems that I personally have tried:

Modem Matrix
ZyXEL U-1496E yes with patch
Zoom 2949 with patch not yet
Hayes Optima 336 yes not yet

A more detailed discussion of my experiences with these modems is below. I believe it should be possible to make caller-id (a.k.a. "calling number delivery" or CND) work with all of these modems; I just haven't got around to making the patches yet.

Zoom model 2949L

I have also tried the Zoom model 2949L (external, serial, about US$80) 56Kx modem, with mixed results. The modem is based on the Lucent Venus chipset, which in principle supports the IS-101 voice AT command set. However, I had a couple of issues with it.

Using the default /etc/mgetty+sendfax/voice.conf file, the modem would not automatically hang up after the caller had left a message, but instead would attempt to receive a data/fax call. I tracked this down to the way that the Zoom modem reports end-of-message to vgetty. If you don't want to know the details, skip the next paragraph.

When the modem (henceforth called the DCE) is put into voice recording mode, it transmits control and status information back to the computer (henceforth called the DTE) by sending "data-link escapes" (DLEs) in-band followed by a character which specifies what the DCE is communicating to the DTE. The sequence DLE q is supposed to mean "silence detected" and is the DCE's way of telling the DTE that the message is finished. The sequence DLE s is supposed to mean "no voice energy" and is the DCE's way of telling the DTE that it doesn't think this is a voice call, so it should try something else (like data or fax). Unfortunately, the folks at Lucent interpreted this differently, and (on page 67 of the document linked above) they return DLE s for "hangup detected". Since most folks hang up after they leave a message, this leads vgetty off to try a data or fax connection when really it was just the end of a normal voice message.

I found a workaround for this, and I have a patch which will enable you to use this modem with vgetty, with the caveat that it will not be able to automatically switch between voice and data/fax modes after this patch is applied.

Nonetheless, the messages recorded by the Zoom modem have the strange property that although they start out fine, they shift to a high speed (and pitch) after just a couple of seconds. I haven't tracked this down yet. I also don't have caller ID working on the Zoom modem yet, but I should soon.

Zoom 3049C

Zoom has used two different chipsets in their 3049 series; the 3049L (L for "Lucent", now Agere) and the 3049C (C for "Conexant", formerly Rockwell). The Lucent modem uses the same chipset as the 2949, with V.92 extensions added.

Hayes Optima 336

This one worked fine right out of the box, except for caller ID (like the ZyXEL). Vgetty identifies this as a Rockwell modem; presumably Hayes is using chipsets produced by Rockwell. Some nice features of this modem are that it has a speaker that plays the message as it is recorded (good for screening calls) and it has speaker/microphone jacks on the side. These things occassionally come up on eBay for very good prices.

Hayes Accura V.92 External (Lucent Venus chipset)

If there are other voice modems out there that you would like to use, let me know (contact info is here) and I'll see what I can do. I might have to ask you to send me the modem.