Intro | Starting IrDA | Communicating | Advanced 

Advanced Linux-IrDA

    Compilation and configuration
    Driver setup
        Serial dongle
        Laptop port in SIR mode
        HP Omnibook 6000 in FIR mode
        Other laptops in FIR mode
        USB FIR dongles
        SIR with irport
        Other laptops in FIR mode
    Debugging Linux-IrDA
        The connection just "hang"
        irattach print "tcsetattr" in the log
        Compilation problems


This tutorial was written by Jean Tourrilhes and adapted for this site. Currently any major Linux distribution have already IrDA support, tools to manage it and some utilities to communicate with various compatible IrDA devices. The following documentation is for die hard kernel & software hackers which want to be on bleeding edge and even to contribute to Linux-IrDA project in general.

A lot of IrDA novices mix up the low level and high level of the IrDA stack. A few words...

  • Low level of Linux-IrDA : this is the part of the IrDA stack dealing with the IrDA hardware on your computer and managing it. The keywords are IrDA driver, IrDA ports (either SIR, MIR or FIR), IrDA dongles and TTY/serial port.
  • High level of Linux-IrDA : this is the part of the IrDA stack dealing with communicating with the other IrDA devices and exchanging the data (the protocol). The keywords are protocol, IrCOMM, IrLPT, OBEX, IrLAN and IrNET.
The low level and high level are totally independent of each other, however each need to be configured properly for what you want to do. The procedure to get IrDA working looks usually like this:
  • Compilation and configuration
  • Set up the low level to recognise your IrDA hardware
  • Verify that the low level works
  • Set up your application on top of the proper high level protocol
I also offer various debugging tips at the end of this document.

Compilation and configuration

Here are the steps to build your own kernel with IrDA paramaters of your choice.

  • Get kernel of your choice, unpack the source in /usr/src or where you feel have enough space to compile it.
  • To do this configure the IrDA stack as a module, enable all options (as module if possible) and the driver/protocols you need (as modules). Prefferably all drivers because don't hurt. You can configure serial port as a module and static is ok as well, except for the NSC or FIR setup. You're warned.
  • Compile kernel iamge, modules and install them:
    > make bzImage
    > make modules
    > make modules_install
  • Install irda-utils-0.9.15 or later
  • Add the following stuff in /etc/modules.conf:
    alias tty-ldisc-11 irtty
    alias char-major-161 ircomm-tty  # if you want IrCOMM support
    # These values are hard-coded in irattach (not instance order)
    alias irda-dongle-0 tekram       # Tekram IrMate IR-210B
    alias irda-dongle-1 esi          # ESI JetEye
    alias irda-dongle-2 actisys      # Actisys IR-220L
    alias irda-dongle-3 actisys      # Actisys IR-220L+
    alias irda-dongle-4 girbil       # Greenwich GIrBIL
    alias irda-dongle-5 litelink     # Parallax LiteLink
    alias irda-dongle-6 airport      # Adaptec Airport 1000 and 2000
    # IrNET module...
    alias char-major-10-187 irnet    # Official allocation of IrNET
  • Create the IrDA devices:
    > mknod /dev/ircomm0 c 161 0
    > mknod /dev/ircomm1 c 161 1
    > mknod /dev/irlpt0 c 161 16
    > mknod /dev/irlpt1 c 161 17
    > mknod /dev/irnet c 10 187
    > chmod 664 /dev/ir*
  • Edit /etc/lilo.conf if you use LILO bootloader or /boot/grub/menu.lst if you use GRUB bootloader and add your new compiled kernel. Then reboot the machine.
Now, it's time to check which hardware you want to make run...

Driver setup

This really depend on the IrDA hardware that you have. I describe a few of the options below. The two safest options are Laptop in SIR mode and Serial dongle.

Serial dongle

The dongle I use is the Actisys 220L+, and the dongle driver is called actisys (see list above). The setup for other dongles should be very similar. I'm also using the first serial port in this example (ttyS0), you may need to adapt to your case.

  • Attach dongle to the serial port, and check which serial port it is.
  • Check if the serial config is ok:
    > setserial /dev/ttyS0
    /dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
  • Start the IrDA stack:
    > irattach /dev/ttyS0 -d actisys -s
  • If you want to unload/stop the IrDA stack just kill all the IrDA applications and do:
    > killall irattach
    > rmmod irtty actisys
    > rmmod irda
Note: all the modern ESI dongles work better with the litelink driver.

Laptop port in SIR mode

SIR (Serial Infrared) is not fast but always work and is easy to set-up, so it's a safe bet. It will work only if the BIOS is set to SIR mode, so don't bother otherwise.

  • Go in the BIOS of the laptop, enable the Infrared port, and set it to SIR mode.
  • While in the BIOS, note the IO address and IRQ assigned to it.
  • Using setserial, find the ttyS* that correspond to this port. Let's assume /dev/ttyS1 (as in my laptop).
  • Start the IrDA stack:
    > irattach /dev/ttyS1 -s
  • Refer to previous example for more
Now, you just need to figure out on which side of the laptop if the IrDA port...

HP Omnibook 6000 in FIR mode

It seems that each laptop has its quirk when it come to FIR mode. I've managed to get my OB6000 to work. Other laptops will be different (different driver, different settings).

  • Go in the BIOS of the laptop, enable the Infrared port, and set it to FIR mode.
  • Add the following stuff in /etc/modules.conf:
    # NSC FIR chipset in the OB6000
    alias irda0 nsc-ircc
    options nsc-ircc dongle_id=0x08
  • Remove the serial driver that gets in the way:
    > setserial /dev/ttyS1 uart none
    > rmmod serial
  • Start the IrDA stack:
    > irattach irda0 -s
The NSC driver gives me some pretty good performance.

Other laptops in FIR mode

There is different FIR hardwares included in the various laptops. Linux-IrDA support some of them (not all) in various degrees (from good to bad). Moreover, it seems that each laptop has its quirk, so it's difficult to list everything here. For this reason, I recommend to make it work first in SIR mode. After that, you can experiement, check the HowTo and query the mailing list... As a rule of thumb, the NSC driver seems to be the most functional (if you set the proper dongle_id, which is either 0x8 or 0x9), and the SMC driver the most problematic.

USB FIR dongles

This driver is included in recent kernel. It's not as efficient as other FIR hardware, but at least is supported and is relatively easy to get working. Also, all the current products are based on the same hardware, and we know most of its bugs. The latest version of the driver has been tested with usb-uhci and usb-ohci.

  • Start the USB stack. If you have an UHCI hardware, it looks like:
    > modprobe usb-uhci
  • Load USB driver and start the IrDA stack:
    > modprobe irda-usb
    > irattach irda0 -s
If you have already some other IrDA hardware configured on the PC, the driver won't load as irda0, so check the message log with dmesg. Also, the driver can manage up to 4 IrDA-USB dongles per PC (that can be increased in the source).

Recently a new type of USB dongle from SigmaTel has appeared on the market which is not compliant with the IrDA-USB specification, and therefore doesn't work with this driver. On the other hand, SigmaTel has made available the full technical specification, so writing a driver for it is possible.

Important note: in recent kernels, the USB team has added a driver called ir-usb. Not only this driver is not compatible with the IrDA stack (the IrDA driver is called irda-usb), but this driver will load automatically before irda-usb, therefore preventing you to use it. Solution: get rid of ir-usb.

SIR with irport

The standard SIR driver is irtty, which uses the standard serial driver and TTY layer. This is the easiest and safest way to get IrDA working. However, the TTY layer adds some overhead and doesn't understand the IrDA protocol, which make it unsuitable in some case (dongle without echo cancelation) and less performant in others (small packets). That is why there is a second driver, irport, which allow the IrDA stack direct access to the serial port. Unfortunately, the procedure to use irport is more complicated and less well tested. Actually, I personally never managed to make irport work reliably on any of my systems.

  • Remove the serial driver that gets in the way:
    > setserial /dev/ttyS0 uart none
    > rmmod serial
  • Load the irport driver and attach the dongle driver.
    > modprobe irport io=0x3f8 irq=4
    > dongle_attach irda0 -d actisys+
  • Start the IrDA stack:
    > irattach irda0 -s

Debugging Linux-IrDA

Of course, I'm sure that you won't get things smooth the first time. Actually, I'm pretty sure you will struggle a little bit. If you get the Obex stuff out of the loop (so, using Ultra or Socket, as described above), the e-Squirt stuff is so simple that if anything doesn't work you can bet that it's the IrDA stack. The first trick is to check is the modules are loaded:

> cat /proc/modules
actisys          1652   1 (autoclean)
irtty            7524   2 (autoclean)
irda           151905  11 (autoclean) [actisys irtty]
This is what a serial dongle setup would look like. If the modules don't show up, check you modules configuration and check the error messages in the log (with dmesg). Then, check the bunch of files in /proc/net/irda:
> cat /proc/net/irda/discovery
IrLMP: Discovery log:

nickname: Jean, hint: 0x8220, saddr: 0x913b1bbc, daddr: 0x5619b45e

> cat /proc/net/irda/irlap
irlap0 state: LAP_NDM
  device name: irda0, hardware name: ttyS0
  caddr: 0x52, saddr: 0x913b1bbc, daddr: 0x5619b45e
  win size: 1, win: 1, line capacity: 4800, bytes left: 4800
  tx queue len: 0 win queue len: 0 rbusy: FALSE mbusy: FALSE
  retrans: 0 vs: 2 vr: 2 va: 0
  qos   bps     maxtt   dsize   winsize addbofs mintt   ldisc   comp
  tx    9600    0       64      1       12      0       0
  rx    9600    0       64      1       12      0       0
> cat /proc/net/irda/irias
LM-IAS Objects:
name: hp:esquirt, id=76371435
 - Attribute name: "IrDA:TinyTP:LsapSel", value[IAS_INTEGER]: 96

name: OBEX:ESquirt, id=76371435
 - Attribute name: "IrDA:TinyTP:LsapSel", value[IAS_INTEGER]: 95

name: Device, id=0
 - Attribute name: "IrLMPSupport", value[IAS_OCT_SEQ]: octet sequence

 - Attribute name: "DeviceName", value[IAS_STRING]: "lagaffe"

name: hp:beacon, id=76371435
 - Attribute name: "IrDA:TinyTP:LsapSel", value[IAS_INTEGER]: 97
There, you can see that the IrDA stack has discovered my Palm V, that my IrDA port is ttyS0, that I'm not connected, and you can also see that I have an e-Squirt application running that has opened a bunch of server sockets (of course, if you haven't started e-Squirt, the IAS won't contains all those sockets).

The ultimate debugging tool is irdadump. You should run irdadump while attempting to connect and check what's happening. A normal irdadump log with a IrDA device in front of the port (not connected) should show something like this (note that ">>" mean breaking long lines):

> irdadump
22:04:48.000713 xid:cmd 6f1e8511 > ffffffff S=6 s=0 (14)
22:04:48.090705 xid:cmd 6f1e8511 > ffffffff S=6 s=1 (14)
22:04:48.180714 xid:cmd 6f1e8511 > ffffffff S=6 s=2 (14)
22:04:48.270734 xid:cmd 6f1e8511 > ffffffff S=6 s=3 (14)
22:04:48.270698 xid:rsp 6f1e8511 < fb48d412 S=6 s=2 Jean >>
  Tourrilhes hint=8220 [ PDA/Palmtop IrOBEX ] (32)
22:04:48.360742 xid:cmd 6f1e8511 > ffffffff S=6 s=4 (14)
22:04:48.450733 xid:cmd 6f1e8511 > ffffffff S=6 s=5 (14)
22:04:48.540762 xid:cmd 6f1e8511 > ffffffff S=6 s=* weblab10 >>
  hint=0400 [ Computer ] (24)

You see my Palm V answering the discoveries of Linux. The Palm shows the infamous "Waiting for sender" pop-up. On the other hand, if the stack is not properly configured (wrong port, wrong driver), or if the device in front is not active, you will get something like this:

22:02:47.988983 xid:cmd 6f1e8511 > ffffffff S=6 s=0 (14)
22:02:48.078981 xid:cmd 6f1e8511 > ffffffff S=6 s=1 (14)
22:02:48.168992 xid:cmd 6f1e8511 > ffffffff S=6 s=2 (14)
22:02:48.258995 xid:cmd 6f1e8511 > ffffffff S=6 s=3 (14)
22:02:48.349018 xid:cmd 6f1e8511 > ffffffff S=6 s=4 (14)
22:02:48.439035 xid:cmd 6f1e8511 > ffffffff S=6 s=5 (14)
22:02:48.529063 xid:cmd 6f1e8511 > ffffffff S=6 s=* weblab10 >>
  hint=0400 [ Computer ] (24)
As you can see, nobody answer us... After that, send a good bug report to the Linux-IrDA mailing list.

The connection just "hang"

One classical problem is the connection hanging just after beeing negociated. The IrDA dump looks like the following:

18:03:28.766071 xid:cmd ffffffff < af28ca67 S=6 s=0 (14)
18:03:28.856067 xid:cmd ffffffff < af28ca67 S=6 s=1 (14)
18:03:28.947685 xid:cmd ffffffff < af28ca67 S=6 s=2 (14)
18:03:29.037383 xid:cmd ffffffff < af28ca67 S=6 s=3 (14)
18:03:29.037549 xid:rsp 977f612c > af28ca67 S=6 s=3 lagaffe >>
  hint=4400 [ Computer LAN Access ] (23)
18:03:29.126099 xid:cmd ffffffff < af28ca67 S=6 s=4 (14)
18:03:29.216071 xid:cmd ffffffff < af28ca67 S=6 s=5 (14)
18:03:29.316257 xid:cmd ffffffff < af28ca67 S=6 s=* tanguy >>
  hint=4400 [ Computer LAN Access ] (22)
18:03:29.316433 snrm:cmd ca=fe pf=1 977f612c > af28ca67 new-ca=ba (32)
18:03:29.417508 ua:rsp ca=ba pf=1 977f612c < af28ca67 (31)
18:03:29.417646 rr:cmd > ca=ba pf=1 nr=0 (2)
18:03:29.666173 rr:cmd > ca=ba pf=1 nr=0 (2)
If you are on the primary, you will see a series of rr:cmd until it times-out. On the secondary, you won't see anything after the ua:rsp and it will eventually timeout. What most likely happening is that the negociated connection parameters don't match. Usually, one end doesn't implement properly the speed that is beeing negociated, so the two nodes can't hear each other after changing speed. And most likely it happens at FIR speeds. Of course, it would be nice to fix the driver, but in the short term the solution is to force the IrDA stack to negociate a lower speed:
> echo 115200 > /proc/sys/net/irda/max_baud_rate
You can of course try lower values, and there is also other parameters you can tweak in this directory. There is another hang similar to that. You may see the IrDA stack "hanging" on transmitting a large packet. This seems due to a bug in the IrDA-USB dongles.
18:03:30.458569 i:rsp  < ca=ba pf=1 nr=6 ns=5 LM >>
  slsap=12 dlsap=10 CONN_CMD TTP credits=0(12)
18:03:30.458740 i:cmd  > ca=ba pf=1 nr=6 ns=6 LM >>
   slsap=10 dlsap=12 CONN_RSP TTP credits=0(12)
18:03:30.466399 rr:rsp < ca=ba pf=1 nr=7 (2)
18:03:30.516548 rr:cmd > ca=ba pf=1 nr=6 (2)
18:03:30.537423 i:rsp  < ca=ba pf=1 nr=7 ns=6 LM >>
  slsap=12 dlsap=10 TTP credits=0 (29)
18:03:30.537663 rr:cmd > ca=ba pf=1 nr=7 (2)
18:03:30.547328 rr:rsp < ca=ba pf=1 nr=7 (2)
18:03:30.555025 i:cmd  > ca=ba pf=1 nr=7 ns=7 LM >>
  slsap=10 dlsap=12 TTP credits=1 (2050)
18:03:30.566804 i:cmd  > ca=ba pf=1 nr=7 ns=7 LM >>
  slsap=10 dlsap=12 TTP credits=1 (2050)
18:03:30.596405 i:cmd  > ca=ba pf=1 nr=7 ns=7 LM >>
  slsap=10 dlsap=12 TTP credits=1 (2050)
It may look a bit different for you, but you get the idea, the packet doesn't goes through and is retried, and the communication just dies there. As we can't fix the hardware, the solution is to force the IrDA stack to transmit smaller packets:
> echo 2000 > /proc/sys/net/irda/max_tx_data_size

irattach print "tcsetattr" in the log

People using FIR drivers (nsc-ircc, smc-ircc...) are often confronted to this simple problem. When they start irattach, it doesn't work and the following message (or similar) is printed in the log&:

irattach: tcsetattr: Invalid argument
This is due to a conflict between the Linux-IrDA FIR driver and the regular Linux serial driver. Both want to manage the same hardware, the serial driver has registered the FIR port as a pseudo serial port and is owning it, and the kernel rightly prevent the FIR driver to get ownership of it (it's first come first serve). The solution is simple. You need to tell the serial driver that it should not manage this port. The safest way is to remove the serial driver:
> rmmod serial
Unfortunately, the trick above doesn't always work (non-modular driver, another serial port in use). Another way is to declare the port invalid:
> setserial /dev/ttyS1 uart none

Compilation problems

Sometimes, when you compile the IrDA stack or some various IrDA package, you may have the compiler complaining the things such as IRLMP_HINT_MASK_SET or IRDAPROTO_ULTRA are not defined. This is because of a mess related to kernel headers and the way most distributions deal with it. If you have the 2.4.X kernel source lying around, the fix is simple. Just copy the header irda.h from the kernel to your include directory:
cp /usr/src/linux/include/linux/irda.h /usr/include/linux
That should fix it.
Home | About | Contact | Documentation | Applications | Download | Resources 

Copyright 2002-2003 Linux-IrDA Project. Released under GNU FDL license.