Blog
Company news and beyond.

Linux HowTo: Setting up Capi4Linux on Debian Linux

February 28, 2004 - Filed in Linux HowTos by Felix
Switching over my main office server system from SuSE Linux to Debian Linux also meant to try to make SuSE-centered and proprietary Capi4Linux work on Debian. Since there is now complete HOW-TO, I decided to write one.

0. Disclaimer

Make sure you have at least one complete backup of your data in a safe place before following anything in this HOWTO. This HOWTO is provided AS-IS. I take no responsibility or liability for damages of any kind that may arouse out of the use of this information. You use it solely on your own risk. If you are not ready to do this, do not continue.

1. Get all packages needed

First, get and install all packages needed:

apt-get install capi4hylafax hylafax-server hylafax-client isdnactivecards isdnutils-base

After that, we need the driver archives from www.avm.de (in Downloads). I used fcpci-suse8.2-03.11.02.tar.gz from AVM's FTP for my FRITZ!Card PCI.

2. Build, insert and test board-specific kernel module

Unlike said elsewhere on the net, Debian does not require you to build a kernel of your own to make use of CAPI 2.0. If you are using a recent kernel-image (e.g. from Debian Sarge), just make sure, you have the corresponding kernel-headers installed on your machine. If in doubt, you can also check for the CAPI 2.0 support in the kernel in the kernel's config file in /boot/config- ..

Now, to build the kernel module, unpack the obtained tar.gz to a temporary place, e.g. /usr/src.

tar -xvzf fcpci-suse8.2-03.11.02.tar.gz

Now, choose the define "id" of your card from this table

Board Interface Define "id"
AVM FRITZ!Card Classic ISA fcclassic
AVM FRITZ!Card PnP PNP fcpnp
AVM FRITZ!Card PCMCIA PCMCIA fcpcmcia
AVM FRITZ!Card PCI PCI fcpci

and use it instead of "fcpci" (or "fcpci" if you use a FRITZ!Card PCI) in below lines

# Change to the unarchived directory
cd fritz

# Change into the actual driver directory
cd src.drv

# Define __fcpci__ through makefile and make the driver (change this line if needed)
CARD=fcpci make

If make should fail, adapt the sourcecode to your need. E.g. if it complains about redefinitions, try to just comment those lines out by prepending a // or putting the respective lines in /* .. */. Tweak the source until there are only warnings left (DO NOT COMMENT OUT ACTUAL CODE!). Then proceed as follows.

# Change back to the unarchived directory
cd ..

# Make a directory /lib/modules/kernel-version/own for our own module
mkdir /lib/modules/`uname -r`/own

# Copy the driver (change this line if needed) to /lib/modules/kernel-version/own
cp src.drv/fcpci.o /lib/modules/`uname -r`/own

# Update module dependencies
# Might bring up a warning about unresolved symbols for fcpci.o, if so,
# read "Appendix A. depmod headaches"
depmod -a

Now it's time to add the modules to /etc/modules. Just append them at the end of the file

# /etc/modules - APPEND these lines

# CAPI
capi
capifs
kernelcapi
capiutil

# Fritz
fcpci

Now, load the modules into the running kernel using modprobe:

oxygen:~ # modprobe capi
oxygen:~ # modprobe capifs
oxygen:~ # modprobe kernelcapi
oxygen:~ # modprobe capiutil
oxygen:~ # modprobe fcpci

If this worked fine, you should now be able to get output by entering capiinfo in a shell

oxygen:~ # capiinfo
Number of Controllers : 1
Controller 1:
Manufacturer: AVM GmbH
CAPI Version: 2.0
Manufacturer Version: 3.101-02  (49.18)
Serial Number: xxxxxxx
BChannels: 2
Global Options: 0x00000039
   internal controller supported
   DTMF supported
   Supplementary Services supported
   channel allocation supported (leased lines)
B1 protocols support: 0x4000011f
   64 kbit/s with HDLC framing
   64 kbit/s bit-transparent operation
   V.110 asynconous operation with start/stop byte framing
   V.110 synconous operation with HDLC framing
   T.30 modem for fax group 3
   Modem asyncronous operation with start/stop byte framing
B2 protocols support: 0x00000b1b
   ISO 7776 (X.75 SLP)
   Transparent
   LAPD with Q.921 for D channel X.25 (SAPI 16)
   T.30 for fax group 3
   ISO 7776 (X.75 SLP) with V.42bis compression
   V.120 asyncronous mode
   V.120 bit-transparent mode
B3 protocols support: 0x800000bf
   Transparent
   T.90NL, T.70NL, T.90
   ISO 8208 (X.25 DTE-DTE)
   X.25 DCE
   T.30 for fax group 3
   T.30 for fax group 3 with extensions
   Modem

  0100
  0200
  39000000
  1f010040
  1b0b0000
  bf000080
  00000000 00000000 00000000 00000000 00000000 00000000
  01000001 00020000 00000000 00000000 00000000

Supplementary services support: 0x000003ff
   Hold / Retrieve
   Terminal Portability
   ECT
   3PTY
   Call Forwarding
   Call Deflection
   MCID
   CCBS

3. Configure HylaFax and CAPI4Hylafax

Open a shell, then call faxsetup (dpkg-reconfigure hylafax-server might be useful also) and capi4hylafaxconfig.

faxsetup
capi4hylafaxconfig

We have copied the file to /etc/hylafax/config.faxCAPI.

Append this line to /etc/hylafax/config:

SendFaxCmd              "/usr/bin/c2faxsend"

Now, start Hylafax and add faxCAPI dynamically, make some symlinks and adjust rights

# Start Hylafax
/etc/init.d/hylafax start
# Will set us up, generate FIFO.faxCAPI
faxmodem faxCAPI
# Stop Hylafax
/etc/init.d/hylafax stop

# Adjust rights
chown uucp /dev/capi20

In the default install, capi4hylafax + hylafax-server do not like each other. Here's the fix, if you (this is especially for the Google-friends ;) get things like

Jan 22 22:05:39 oxygen FaxQueuer[2865]: HylaFAX (tm) Version 4.1.8
Jan 22 22:05:39 oxygen FaxQueuer[2865]: Copyright (c) 1990-1996 Sam Leffler
Jan 22 22:05:39 oxygen FaxQueuer[2865]: Copyright (c) 1991-1996 Silicon Graphics, Inc.
Jan 22 22:05:39 oxygen HylaFAX[2867]: HylaFAX INET Protocol Server: restarted.
Jan 22 22:05:39 oxygen HylaFAX[2867]: HylaFAX Old Protocol Server: restarted.
Jan 22 22:05:39 oxygen HylaFAX[2867]: HylaFAX SNPP Protocol Server: restarted.
Jan 22 22:05:39 oxygen FaxGetty[2869]: Syntax error at line 149, missing ':' in "{"
Jan 22 22:05:39 oxygen FaxGetty[2869]: Syntax error at line 289, missing ':' in "    {"
Jan 22 22:05:39 oxygen FaxGetty[2869]: Syntax error at line 394, missing ':' in "    }"
Jan 22 22:05:39 oxygen FaxGetty[2869]: Syntax error at line 395, missing ':' in "}"
Jan 22 22:05:39 oxygen FaxGetty[2869]: OPEN /dev/faxCAPI  HylaFAX (tm) Version 4.1.8
Jan 22 22:05:47 oxygen FaxGetty[2869]: /dev/faxCAPI: Can not initialize modem.
Jan 22 22:07:04 oxygen FaxGetty[2869]: Unable to setup modem on /dev/faxCAPI; giving up after 2 attempts
Jan 22 22:07:04 oxygen FaxGetty[2869]: CLOSE /dev/faxCAPI
Jan 22 22:07:04 oxygen FaxQueuer[2865]: MODEM WEDGED: bin/wedged "faxCAPI" "/dev/faxCAPI"
in your /var/log/messages logfile (you won't get these if you follow below instructions, this is the actual "fix" this HOW-TO provides. All lines that are bold above should NOT turn up at all when following this HOWTO).

Edit /etc/init.d/hylafax and change one variable on top (bold line).

#!/bin/sh
# Start or stop HylaFAX

PATH=/sbin:/bin:/usr/sbin:/usr/bin
HYLAFAX_HOME=/var/spool/hylafax
FAXGETTY=/usr/bin/c2faxrecv
FAXMODEM=/usr/sbin/faxmodem

if [ -f /etc/default/hylafax ]; then
  . /etc/default/hylafax
fi

test -x /usr/sbin/faxq || exit 0
test -x /usr/sbin/hfaxd || exit 0
test -f /var/spool/hylafax/etc/setup.cache || exit 0

echo_fax_devices()
{
  for device in config.tty[MS][0-9] config.faxCAPI; do
    if [ -f "$device" ]; then
      echo "$device"
    fi
..

Alternatively, you could try to do this on the filesystem basis and exchange faxgetty for c2faxrecv (this is not tested, but I don't see why it should not work):

# backup old faxgetty
mv /usr/sbin/faxgetty /usr/sbin/faxgetty.orig

# make faxgetty a symbolic link to c2faxrecv
ln -s /usr/bin/c2faxrecv /usr/sbin/faxgetty

Hylafax's faxgetty and c2faxrecv run as own server (as the Debian package would suggest) will NOT work. Use above workaround.

4. Start HylaFax

Since this HOW-TO is mostly written from memory, I hope no configuration option was forgotten :)
Now, its time to start the daemon(s).

/etc/init.d/hylafax start

Now, check the output of /var/log/messages and /var/log/hylafax/capi4hylafax and make adjustments as needed. This is, how it should look like:

/var/log/messages

Jan 22 22:34:52 oxygen FaxQueuer[3426]: HylaFAX (tm) Version 4.1.8
Jan 22 22:34:52 oxygen FaxQueuer[3426]: Copyright (c) 1990-1996 Sam Leffler
Jan 22 22:34:52 oxygen FaxQueuer[3426]: Copyright (c) 1991-1996 Silicon Graphics, Inc.
Jan 22 22:34:52 oxygen HylaFAX[3428]: HylaFAX INET Protocol Server: restarted.
Jan 22 22:34:52 oxygen HylaFAX[3428]: HylaFAX Old Protocol Server: restarted.
Jan 22 22:34:52 oxygen HylaFAX[3428]: HylaFAX SNPP Protocol Server: restarted.
Jan 22 22:34:52 oxygen kernel: kcapi: appl 7 up
Jan 22 22:34:52 oxygen kernel: kcapi: appl 8 up

/var/log/hylafax/capi4hylafax

Jan 22 22:34:52.60: [ 3430]: c2faxrecv - INFO: Started in Hylafax mode and waiting on incoming calls.

5. Check your logs

After having gone through all the difficulties above and having managed to set up a working CAPI + fax system, make sure you check your logs. I had the box running stable for about a week after setup but noticed that /var/log/messages was now full of

"eth0: Too much work at interrupt"

messages. If you already had those before going through the whole process, I would personally not worry. However, turns out, for me, this only appears in the logs with fcpci inserted into the kernel. I had several crashes, oopses, panics and lockups due to fcpci, some of which corrupted filesystem data. Sadly, the old module code I used under SuSE Linux and which worked rock-stable can't be used with current Debian kernels, since AVM compiled their closed-source part of the driver with gcc 2.x at that time and inserting modules containing code from gcc 2.x into gcc 3.x kernels does not work. Welcome to the joys of closed-source drivers. So, after finding that out, I stopped using the whole AVM stuff for now, since I need a reliable and rock-solid machine. If anybody has an idea on where the problem is located regarding this, you're welcome to tell me :)

Appendix A. depmod headaches

On Debian systems, depmod often (always?) can't resolve symbols in fcpci.o. A

depmod -a -e
will then give you output like this
# depmod -a -e
depmod: *** Unresolved symbols in /lib/modules/2.4.24-1-k7/misc/fcpci.o
depmod:         _mmx_memcpy
depmod:         enable_irq
depmod:         __kfree_skb
depmod:         alloc_skb
depmod:         __release_region
depmod:         tq_immediate
depmod:         attach_capi_driver
depmod:         kmalloc
depmod:         _ctype
depmod:         pci_enable_device
depmod:         __check_region
depmod:         vfree
depmod:         detach_capi_driver
depmod:         cpu_raise_softirq
depmod:         pcibios_present
depmod:         free_irq
depmod:         __out_of_line_bug
depmod:         bh_task_vec
depmod:         __udivdi3
depmod:         kfree
depmod:         disable_irq
depmod:         request_irq
depmod:         skb_over_panic
depmod:         pci_find_device
depmod:         __tasklet_hi_schedule
depmod:         jiffies
depmod:         __vmalloc
depmod:         softnet_data
depmod:         __request_region
depmod:         printk
depmod:         irq_stat
depmod:         ioport_resource

For stable operation, all symbols should be resolved. The solution I found here is to adapt the makefile in src.drv from

# As propsed by /usr/include/linux/version.h...
DEFINES = -DMODULE -D__KERNEL__ -DNDEBUG \
          -D__$(CARD)__ -DTARGET="$(CARD)"

CCFLAGS = -c $(DEFINES) -O2 -Wall -I $(KRNLINCL)

to

DEFINES = -DMODULE -DMODVERSIONS -D__KERNEL__ -DNDEBUG \
          -D__$(CARD)__ -DTARGET="$(CARD)"

CCFLAGS = -c $(DEFINES) -march=athlon -O2 -Wall -I $(KRNLINCL) \
          -include $(KRNLINCL)/linux/modversions.h

If your kernel is optimized for something different than athlon (i.e. Pentium IV), replace athlon with the respective argument (i.e. i686 for Pentium IV).

In my case, I still had

depmod:         __udivdi3

left after that. As research yielded, this is 64 bit division function. Thanks to google, without having to look through the sources myself, I found a solution for this also here. In src.drv/lib.c, replace this code

unsigned long os_msec (void) {
        return (((unsigned long long) jiffies) * 1000) / HZ;
} /* os_msec */

with this

unsigned long os_msec (void) {
        unsigned long j;

        j = jiffies;

        return (j * (1000 / HZ) + (j * (1000 % HZ)) / HZ);
} /* os_msec */

As a software developer in professional life, I may be permitted to note at this point that AVM's construct has a maximum lameness factor (no offence meant!):

First, you don't use 64-Bit operations, if you can avoid it, second, proper code always has brackets around return results, third, "casting is your friend"(tm) and fourth, specifying a 64 bit value as value for the return statement of a function declared to return a 32 bit value is just plain ... let me say it that way: that line is a masterpiece in its own right :)

Ok, now that everything's cleaned up, enter a

make clean

in the src.drv directory, then proceed as suggested earlier to build and install the module. depmod should no longer complain now.

Appendix B. Further references


Last updated: 28.02.2004

0 comment(s):

Write a comment

The comments are closed for this article.