Version 2 of infrared

Updated 2003-12-27 06:18:07

URL:

    http://45.free.net/~akovalenko/irdasock-latest.tar.gz
    http://45.free.net/~akovalenko/irdasock-win32-stubs.zip

This extension enables Tcl to connect to IrDA (infrared) services on Win2K and Linux (with limitations for Win98).

Introduction

Communication with devices through an infrared link is usually performed with sockets. The special address family for infrared links (AF_IRDA) is supported on Linux and Windows.

Irdasock extension opens such sockets as Tcl channels. Besides that, it can list all connected devices with their numeric IDs, names and hints.

    % package require irdasock 1.0
    % irda::discover
    {1176300784 R520 {PnP Modem Comm OBEX}}
    % 

You can see here an example of [irda::discover] result, which gave us the device id 1176300784, with name "R520" (it is my mobile phone) and hints {Pnp Modem Comm OBEX} describing which services it claims to support.

When the discovery is done and the target device id is known you can connect to the specific service:

    % set id [lindex [irda::discover] 0 0]
    1176300784
    % set fh [irda::connect $id IrDA:IrCOMM]
    sock212
    % puts $fh ATZ
    % flush $fh
    % gets $fh
    ATZ
    % gets $fh
    % gets $fh
    OK

Now you can do everything you need with the socket $fh. In case of a mobile phone, you can use my gsm library to read and send SMS...

The service which you connect to must use TinyTP protocol. OBEX and IrCOMM both work this way.

Commands

    irda::discover

List connected devices.

The command returns a list of the following structure:

  {Dev1-Hw-Addr Dev1-Name {Hint1 Hint2 ... } }
  {Dev2-Hw-Addr Dev2-Name {Hint1 Hint2 ... } }

Each device has a hardware address that you can pass to [irda::connect]. This address is not permanent, however: if a device will leave the scope of IR receiver for a significant time interval (30 seconds or so), it will be given a new address when it returns.

The device name is more permanent. It's an ideal choice to show up in a message like "Your $gadget is now connected!"

Hints describe a nature of the device and what services it can be expected to provide. All possible hints are the following:

    PnP, PDA, Computer, Printer, Modem, Fax, LAN,
    Telephony, Server, Comm, Message, HTTP, OBEX.

As an example, my Ericsson R520 cell phone gives {PnP Modem Comm OBEX} in the list of hints.

    irda::connect ?-mode tinytp|ircomm? device-addr service-name

Connect to a device and return a channel handle.

Here, device-addr is one of the addresses returned by [irda::discover]. Service-name is something like IrDA:IrCOMM or IrDA:OBEX.

The -mode option sets the special handling of the IrCOMM control data. As these data are transmitted in regular TinyTP frames, you will receive them in a random places of a byte stream unless some countermeasures are taken.

There's no need to specify -mode option in common cases, as it defaults to "ircomm" when the service name is IrDA:IrCOMM and to "tinytp" otherwise. The option must be specified only if you're connecting to some serial port emulating service with the name different from IrDA:IrCOMM (it's rare), or to some non serial port emulating service which is named IrDA:IrCOMM (it's almost impossible).

Implementation details

As Tcl supports TCP/IP, it contains a lot of code to manage sockets, and only a small subset of this code is TCP/IP-specific. So I decided to write an extension for Tcl which creates AF_IRDA sockets and then simply passes them to Tcl channel infrastructure.

The first drawback of this solution was that fconfigure was confused when trying to getpeername() on my sockets. So I decided to use stacked channels. The next version stacks my channel over Tcl's socket and overrides the functions that handle channel-specific fconfigure options.

The IrCOMM service was (and still is) another headache. As IrCOMM control data are received in regular TinyTP packets, we need to know packet boundaries to strip these data off. There is a fine setsockopt() on Windows'2000 that lets the irda stack do the job. There is no such option on Linux - but it's easy to know the next packet size without upsetting the Tcl socket infrastructure. So I use the platform-dependent solution to achieve the cross-platform result. The stacked channel procedures handles IrCOMM control data on Linux, but not on Windows'2000, where setsockopt() is enough.

Porting the Linux solution to Windows would be useful too, as Windows'98 cannot do the necessary setsockopt().

-- Anton Kovalenko