Valid HTML 4.01 Transitional

Setting Up a FAX Server

James F. Carter <jimc@math.ucla.edu>, 2008-08-02

Contents

I needed to FAX a prescription to my pharmacist. Formerly on our home office machine we had Windows XP Professional, which has FAX software, but we upgraded to Windows Vista Home Premium, which I discovered does not have it. One strategy would have been to upgrade to Vista Business or Ultimate, but we decided that that was unreasonable.

Since I'm a Linux geek, I of course proposed doing the job on our home server.

The Modem

One should approach hardware selection in this order:

According to Conexant's hype about the CX93010 chipset, it should be quite popular among modem designers, and it is very likely that other USB, PCI and DB-9 modems include it, but their sales information fails to identify the chipset. This document declares (correctly) that the chipset works with Linux. It identifies ITU V.253 as the standard which the answering machine commands follow. The chipset can recognize when the remote partner hangs up or if a local extension is picked up.

Hardware Setup

You just plug in a USB device and it works, right? Yeah, sure. These messages were seen in syslog upon hotplug:

But no serial device appeared. It turns out that you need to do this: (Credit to this howto from the Irish Linux Users' Group.)

modprobe usbserial vendor=0x0572 product=0x1321

Once that was done, these devices were created by udev:
Device Major Minor Function
/dev/bus/usb/001/017 189 16 USB Device
/dev/usbdev1.17_ep00 254 19 ?
/dev/usbdev1.17_ep02 254 22 CDC Data
/dev/usbdev1.17_ep81 254 20 Abstract Modem
/dev/usbdev1.17_ep82 254 21 CDC Data
/dev/ttyUSB0 188 0 Serial Line

The modem's USB ID (vendor and product codes) do not appear in /lib/modules/$version/modules.usbmap or anywhere else, so only limited hotplug support is possible out of the box. I added two automation scripts to make the modem function after hotplugging (particularly, when coldplugged after a reboot):

You need to load the usbserial driver specifying the vendor and product codes. Put this in a file in /etc/modprobe.d. The given command lines will be used when cdc_acm, the abstract modem driver, is to be installed or removed. But things get more complicated if two different brands of modem are present on the same system.

install cdc_acm /sbin/modprobe --ignore-install cdc_acm ; /sbin/modprobe usbserial vendor=0x0572 product=0x1321
remove cdc_acm /sbin/modprobe -r usbserial ; /sbin/modprobe -r --ignore-install cdc_acm

With this done and usbserial loaded, I was able to use Minicom (described at the end of the document) to dial the modem and make a data connection to a modem at work, as a test.

I'm looking ahead to using a pair of these modems, one for each of our two phone lines, as a telephone answering machine. The FAX configuration needs to refer to the modem(s) explicitly, but USB devices tend to appear during hot or coldplug in a random order and so to have random minor device numbers and names. An invariant symbolic link can help this, created by a udev rule. First locate the correct device (here it will be /dev/ttyUSB0) and do:

udevinfo -q path -n ttyUSB0
It prints a path relative to /sys, represented by $path in the next command line:
udevinfo -p $path -a
It prints quite a lot of material (you might pipe it into less). Pick out attributes that uniquely identify the device and copy them into a udev rule. You can pick up to five attributes, using those for the device itself (first stanza) and any one ancestor directory. The rules belong in /etc/udev/rules.d and lexically earlier filenames have priority; my filename is 25-jimc.rules. My rule for the FAX modem is (all on one line):
ATTRS{idVendor}=="0572" ATTRS{idProduct}=="1321" ATTRS{serial}=="24680246" SUBSYSTEM=="tty" SYMLINK="faxmodem0"
Since the product code is in an ancestor device you need SUBSYSTEM=="tty" so the symlink will be made to the correct device; otherwise the link would be made to usbdev1.19_ep81.

HylaFAX Server Software

As one way to send a FAX I'm going to configure a network printer. Since I use CUPS for printing, I'll be using fax4CUPS (see below). This software supports four FAX server programs, from which I need to pick one:

capisuite

This is for ISDN. Useless for us.

efax

Quoting from their page: EFAX is a nice simple program for single user systems. It's attractive, but we want a Windows client and it is not intended for network use. If it's sufficient to print outgoing FAXes to a network printer, and for incoming FAXes to be mailed to a secretary or left as files on the server, then you may like efax.

mgetty-fax

Simple, available, but sparse. Included in SuSE. Same comments apply as to efax. Note: the HylaFAX documentation mentions coordination with mgetty. That is not the one that comes with this package.

HylaFAX

This is the benchmark FAX server software for Linux. Included in SuSE. All the good Windows clients talk to HylaFAX. This is the one we will install.

Hylafax has good online documentation which you should read. I followed the instructions for Basic Server Configuration. Here are some notes on steps which were not obvious.

For testing, or in gateway scripts, you can use the sendfax command. See its man page for usage instructions. Incoming FAXes are stored in ~fax/recvq; client programs can retrieve them by contacting the HylaFAX daemon hfaxd on port 4559.

It all seems to be working, including through reboots. It sends faxes originating on the local machine via the sendfax command itself, or by fax4CUPS (printing on the FAX printer).

Recipient Format: The main information in the recipient field is the phone number of the remote FAX machine, but the full name of the recipient can be prepended, separated with an at sign, like this (from the sendfax man page): Sam Leffler@+1.415.555.1212. The full name is removed and inserted in the cover page. Hyphens, dots or blanks can be added to the phone number for readability; they are ignored.

Cover Pages: By default, HylaFAX creates a cover page for each transmitted FAX. However, some packages, specifically fax4CUPS, suppress this cover page by giving the -n option to sendfax. You will need to hack the backend script to turn it back on. The cover page can be customized; it is left as an exercise to the reader to locate the default template file, view it (use faxcover, which has a man page), and substitute a custom template (with SuSE, see /usr/share/doc/packages/hylafax/latex-cover-1.04/README).

Clients and Support Software

fax4CUPS

CUPS is one of the currently more popular printing subsystems for Linux, using the IPP protocol which Windows also uses. Fax4CUPS is a CUPS backend that sends the printed job as a FAX. I downloaded and installed the RPM package (20 Kb). Here are some notes on the installation.

Its post-install scriptlet got an error (nonfatal): it wants to execute /etc/rc.d/init.d/cups, which is what they do in Red Hat, but not in UnitedLinux (SuSE). It has variants (discussed in a previous section) for these FAX systems: capisuite, efax, mgetty-fax and HylaFAX.

The URI used in CUPS for HylaFAX is hylafax:/local. Using the CUPS administrative interface, you set up a new printer to use this URI. Unfortunately, with cups-1.2 you don't get the opportunity to specify the URI; the only choices are efax on the first or second serial port. Finish creating the printer, then stop CUPS, and edit /etc/cups/printers.conf. For your printer, find DeviceURI and change to hylafax:local. Start CUPS again.

Upon installation you need to create /etc/sysconfig/fax with these variables. Except the provided backend script /usr/lib/cups/backend/hylafax does not read the file! You need to either set the defaults in the script and/or hack the script to read the sysconfig file as advertised by the documentation.

You also need to add to /etc/sudoers a line so that sudo -u $JOB_OWNER /usr/bin/sendfax will be allowed, like this one, assuming that CUPS runs as the user lp. This implies that the job owner, the loginID which the printing client reports to CUPS, must have an account on the CUPS/HylaFAX server.

lp ALL=(ALL) NOPASSWD: SETENV: /usr/bin/sendfax

Fax4CUPS assumes that it will not get enough useful parameters to create a cover page (q.v.), and suppresses this feature. However, if you're sending to an office it's important to let at least the individual recipient's name be shown; the needed recipient format is discussed here. You need to hack the backend script so it does not specify the -n (no cover page) switch to sendfax.

When printing, set the job name (with the -J option of lpr or -t option of lp) to the recipient (phone number). The format of the recipient is anything acceptable to HylaFAX (q.v.) Acceptable content to be printed is anything that CUPS can convert to PostScript, i.e. just about anything.

You can also set these CUPS options using the -o switch of lp and lpr:

faxy

It is assumed that a web server runs on the same machine that hosts HylaFAX. Faxy is a PHP script which is a front end to HylaFAX. It can display FAXes that have been received, archive or delete them, or accept an uploaded content file (text/plain, PostScript, or PDF) and send it as a FAX. Button labels and documentation are in Italian.

Actually it's a pretty nice program if you have some modest ability to work with languages you don't know. I do have some criticisms, which are given at the end of this document. To install, you need to edit the configuration file .../faxy/config.php.

When our Windows user wants to work with FAXes, Faxy is going to be the main interface to HylaFAX.

Faxy's installation instructions assume that the webserver will use mod_php5 (for Apache, or the equivalent on other webservers). However, for security reasons I execute PHP as a CGI script. To make this work you need to make the Faxy program units executable (chmod a+rx .../faxy/*.php), and you need to register PHP with binfmt_misc (described at the end of this document).

WHFC (Windows HylaFAX Client)

This program communicates across the net with the HylaFAX server. The documentation says it needs server version 4.0 through 4.3; I suspect this means it uses the new protocol and will work on 4.0 and up. It can execute on Windows NT, 2000, XP and Vista. The current version is able to display FAXes if a TIFF viewer is installed (see the above URL for recommended viewers).

I installed it successfully (on Vista), and it probably would have functioned properly in a less demanding environment. However, the server has an aggressive firewall, and HylaFAX uses the FTP protocol on its own port; evidently it's smart enough to use passive FTP when the active style is not possible. But the server also blocked passive connections from the client to arbitrary server ports. I was not able to figure out an iptables rule (using the helper module) that would apply the FTP helper to the HylaFAX port.

So WHFC is going to have to wait until the firewall problem is solved.

Winprint HylaFAX

This is a printer emulator for Windows that sends jobs to HylaFAX. It can pop a dialog box to ask for the recipient (phone number); see here for formatting. However, it is advertised as working on Windows NT through XP. On Vista it tries to create its special port and gets permission denied. So I won't be able to use Winprint HylaFAX.

To-Do List

Miscellaneous

Modern AT Commands

TDC in the UK is a vendor of modular modems to be included in embedded systems. Look about 65% through this page; there's a list of modern AT commands. Strictly speaking, "N Baud" means the rate of signalling units per sec. With fancy encoding you can pack multiple bits per signalling unit, so it is not correct to equate bits/sec with baud.

How to Use Minicom

When using it for the first time, execute as root: minicom -s. Edit settings as appropriate, then save, which creates the systemwide configuration file /etc/minirc.dfl. In particular, you specify here the serial line to which the modem is attached: for me, /dev/ttyUSB0 or its symbolic link /dev/faxmodem0. Once /etc/minirc.dfl is created you can just invoke it as minicom, no command line arguments.

Once minicom is started you can use these escape sequences. The letters are not case sensitive.

However, ^AH and ^AX do not seem to actually hang it up; you need to tell the modem ATH0.

Criticisms of Faxy

Faxy is a nice program and does pretty much what I want, but I've found some problems with it.

PHP Support with Binfmt_misc

Faxy is a set of PHP programs. For security reasons I do not run mod_php5 on my Apache webserver; rather I execute PHP scripts using a self-compiled interpreter for the CGI SAPI. (My distro does not understand the importance of doing this when a variety of non-cooperating users have UserDirs on one webserver -- but that's another rant.)

The most convenient way to make the CGI SAPI happen is to make the PHP scripts executable (chmod a+rx .../faxy/*.php) and then activate binfmt_misc. You need to do these steps:

I made an init script in the SuSE/Red Hat/SysV style to do this at boot time.

Using the Voice (FXO) Features

This project was not started with voice in mind. However, the Conexant CX93010 chipset turns out to have voice capability, intended to turn your computer into a telephone answering machine. Beyond that, if it can answer (terminate) a call, dial (originate) a call, and send and receive voice in either circumstance, then this modem is a legendary FXO POTS bridge enabling VOIP service on the home server: just like Skype but locally controlled and lacking the negative political and protocol aspects of the commercial company.

In case I want to invest the time to make this work, here are notes on the research I've done so far.

This howto on modem multiplexing (dated 2001-02-27) is frequently linked to. Here's a summary of what to do to serve data, FAX and voice on a suitably equipped modem.

Check out VOCP for a fancier setup. VOCP looks like it has a lot of functions we want, including:

For full-blown VOIP, Asterisk is the benchmark open-source PBX program.