Setting up your own WAP Gateway - to control your home appliances

All copyrights and trademarks on this page belong to each respective owner. The copyright of all materials on this page belongs to Mike Björklind unless otherwise stated.

This page may be opened in its own browser by clicking this link.

© 2002 - Mike Björklind. All rights reserved.

Hardware, software, services and settings needed to set up a WAP gateway, the way I did:

  1. A Noname PC clone with a 133 MHz Pentium. 20 MB RAM, 10 GB disk.
  2. An old graphics board with no particular features (un-important).
  3. Red Hat Linux 7.1 "standard server". Kernel 2.4.2-2.
  4. A Winbond W6692 based ASUScom ISDN PCI board.
  5. hisax and isdn drivers - to enable communication through the ISDN board - probably included as modules in your kernel already.
  6. ppp (RPM package ppp-2.4.0-2) - to handle the session from a GSM phone.
  7. An ISDN fixed-line subscription... (Mine is a Telia Euro DSS1)
  8. A WAP 1.1 enabled GSM phone (I'll describe using a Nokia 6210, which I'm using)
  9. The Apache 1.3.19 web server.
  10. The libxml2 package (I've just installed the libxml2. Not the libxml2-devel).
  11. The Kannel WAP Gateway.
  12. The mgetty terminal daemon - a getty on steroids.

Additional linx of possible interest to those among you who want to try this:

Linux Server for Beginners

Linux Basic Setup (basic for some of us)

Linux Wap Dial-In Setup

Linux: ISDN4LINUX - Dial-In, by Peter Bieringer

GSM over V.110 Mini-HOWTO, by Ola@Sigurdson.SE

All information in this page has been verified to the outmost possible extent. All low-level link negotiation information has been verified with five different mobiles; Nokia 3330, Nokia 5210, Nokia 6210, Ericsson R320s and Ericsson T68.

Install the Linux server and include support for ISDN. Install the ISDN PCI board (you know - open the box, find an empty PCI slot , plug in the board and remember it must be properly seated) and check that you don't get any conflict with already existing hardware (happened to me - my CD suddenly disappeared when the ISDN board snatched its IRQ11)). You don't need to use any of pnpdump or isapnp to make the PCI board communicate. The drivers are compiled as modules and loaded with modprobe. I'm not sure the type and protocol settings are necessary but it doesn't introduce any conflicts for me:

# The modprobe below loads the isdn module first and then the
# hisax module, which is dependent of the isdn module.
# You will get device handling of devices named ttyIx - where
# x is 0, 1 and so forth in your /dev directory when loading
# the isdn module by loading hisax...
#
# type=36 selects support for the W6692 chip.
# protocol=2 selects the Euro DSS1 standard. Check the file
# README.HiSax that come with the installation of the RPM
# package kernel-doc (with my version, 2.4.2-2, of kernel-doc
# anyway). The file is written by Karsten Keil - all credits to
# him and all work he has put into it!

modprobe hisax type=36 protocol=2

In the isdn4k-utils package you'll find utilities such as isdnlog, isdnrep and so forth - programs and tools to set up a whole enterprise solution around an ISDN connection. I'm not explicitly using any of the available extra packages, such as xisdnload, but xisdnload may come in handy (provided that you're using X), from time to time. Maybe I'll return to the subject in the future with some ideas and application(s) around this (major part of the documentation is in German).

rpm -iv isdn4k-utils-3.1-39

Install the Apache web server (probably already done when installing Linux). Verify that Apache works by executing either lynx or netscape:

# Select the browser you think easiest verifies your Apache
# installation (of course you can verify Apache by running
# both of the suggestions, but what will be gained?):
#
# If you're using X:
netscape http://localhost/ &
# If you're happy with a regular prompt:
lynx http://localhost/

If Apache doesn't work the way you expect it to - you're in for quite a bit of digging around in the HOWTO's and manuals around it. Since this page is not about Apache... Good luck!

Provided your Apache is working properly, edit the file /etc/httpd/conf/httpd.conf to add support for WAP. In the standard httpd.conf file provided after installing Apache, starting at line 810 where a lot of MIME types are added, I inserted the 4 lines below:

AddType text/vnd.wap.wml wml
AddType text/vnd.wap.wmlscript wmls
AddType application/vnd.wap.wmlc wmlc
AddType application/vnd.wap.wmlscriptc wmlsc

Before installing the Kannel WAP Gateway, install the libxml2 package:

rpm -iv libxml2-2.4.13-1

Install the Kannel WAP gateway and Edit the file /etc/kannel/kannel.conf. For the WAP gateway, you don't need to make any changes in the /etc/kannel/smskannel.conf file. I'll get back to setting up a local SMS gateway later, when I've made it myself. My kannel.conf file looks like below:

#
# THIS IS THE CONFIGURATION FILE FOR WAP KANNEL
#
# WAP Kannel is run like this:
#
#   /etc/rc.d/init.d/kannel start
#
# After that you can use your 6210 to test this out.
#
# For any guidelines to set up your 6210, see Kannel FAQ
# on Kannel WWW pages at http://www.kannel.3glab.org/
#
# For any modifications to this file, see Kannel User Guide.
# If that does not help, send email to devel@kannel.org
#
# In both groups, core and wapbox, you may enable logging if
# you like. The /tmp/wapbox.log file will be the bigger one.
#
#    Kalle Morjola May 2000
#    Mike Bjorklind Dec 2001
#

group = core
wapbox-port = 9200
admin-port = 13000
admin-password = bar
wdp-interface-name ="*"
#log-file = "/tmp/kannel.log"
#log-level = 0
box-deny-ip = "*.*.*.*"
box-allow-ip = "127.0.0.1"
#admin-deny-ip = ""
#admin-allow-ip = ""
#access-log = "access.log"

group = wapbox
bearerbox-host = localhost
#log-file = "/tmp/wapbox.log"
#log-level = 0
syslog-level = none

To make your WAP gateway answer calls from your mobile (or your friends'), you need to set up the mgetty properly (Mgetty+Sendfax documentation and FAQ - either of greenie or doering). First of all, the mgetty is not installed by default. Find the RPM package for it on the web and install it. The version shall, at least, be 1.1.25 or it will most probably fail serving any mobile ISDN calls:

rpm -iv mgetty-1.1.25-2.rpm

Work is ongoing in the area of making "analog" wap dialin connections. One of the problems is that an external modem is easier to make use of, from within Linux, to resolve the caller id of the mobile dialing in - and I simply don't own such a modem and I'm for sure not buying one to provide a solution for a problem I don't have... The problem is not so easily solved by just using any of the 3 or 4 internal analog modems in my possession since Linux keep thinking that any internal modem is a "WinModem" (stupid hardware) and handles it accordingly. The solution here is complex enough, without introducing analog calls.

The mgetty package creates a directory - mgetty+sendfax - in /etc where it puts three files (at least), for you to config the mgetty with: dialin.config, login.config and mgetty.config. Below I've listed my files contents but I've changed my phone numbers so you all won't start making calls to me - would probably rotate my /var/log/messages like crazy, since all calls are logged in the messages file.

The directory where the files reside is /etc/mgetty+sendfax, containing:

# dialin.config
# This file may be used setting up other responding services than
# answering mobile calls. I can set up answering of data calls or fax
# calls from certain or all callers.
# For example:
# list of my friend's data lines:
#3433535, 7445343, 5551212
# Dad's fax
#4164646777
#
# Mike's mobile
733123461
# Staffan's Mobile
733123462
# Staffan's Private mobile
707797288
# Nils' mobile
733123463
# Cathrines mobile
733123464
# Johan's mobile
733123465
# Anders' mobile
733123466
# Erika's mobile
733123467
# Ulla's mobile
705221202
# Disallow [other] calls from numbers matching the following prefix:
#!416
#
# Disallow that speed dialer that keeps hitting my machine
#!3444444
#
# Allow all calls with following prefix:
#832, 555
#
# Don't allow calls without any caller id:
#!none
#
# Disallow all other calls:
#!all
---------------------------------------------------------------
# login.config
/AutoPPP/ -    a_ppp    /usr/bin/pppd file /etc/ppp/options.wap
---------------------------------------------------------------
# mgetty.config
#
# mgetty configuration file
#
#speed 9600
# ----- port specific section -----
# Here you can put things that are valid only for one line, not
# the others.
#
# In the init-chat below, PRXPHONE shall be substituted with your
# own attributes: PRX is your area code - 031 for Göteborg, 08 for
# Stockholm etc, PHONE is your ISDN subscriber line, for example
# 7462000, 3402131 etc.
#
# After a lab on 2002-03-02, we found that the S19 register
# differs between different models/makes of mobiles.
# The information we found is inserted below as ttyI1.
#
# Port ttyI0 has S19 set to 197; Nokia 3330, Nokia 5210, Nokia 6210
# and Ericsson T68
# Port ttyI1 has S19 set to 0; Ericsson R320s
port ttyI0
init-chat "" AT&F OK AT&EPRXPHONE&R9600S19=197 OK
port ttyI1
init-chat "" AT&F OK AT&EPRXPHONE&R9600S19=0 OK

To make mgetty run properly, you must add it to the /etc/inittab file. mgetty has a lot of switches, where the -x, for example, is the debug flag. -x takes a numeric argument stating the debug level - 9 is very loud and prints a lot in your /var/log/messages file. The part in my /etc/inittab concerning mgetty is listed below (The m2 line was inserted after a lab made on 2002-03-02):

# Excerpt from my /etc/inittab file
# I found that setting the baudrate (-s 9600) of my /dev/ttyI0
# device works better if I do it here, rather than anywhere else.
# I've saved my debug (#m1 containing the -x 9) version to be
# able to swiftly turn it on again, just if needed of course...
# The m1 line is for Nokia 3330, Nokia 5210, Nokia 6210, Ericsson
# T68...
# The m2 line is for Ericsson R320s
#m1:35:respawn:/sbin/mgetty -x 9 -s 9600 -n 1 -D /dev/ttyI0
m1:35:respawn:/sbin/mgetty -s 9600 -n 1 -D /dev/ttyI0
m2:35:respawn:/sbin/mgetty -s 9600 -n 1 -D /dev/ttyI1

To reread the /etc/inittab execute the command init:

init q
or
killall -HUP init

To enable the pppd daemon servicing properly, the /etc/ppp/options.wap file must be created with content very (!) similar to my own example below. The IP-addresses below are "The IP address of the machine where Kannel is running":"The IP address a calling mobile is given during a session":

-detach
default-asyncmap
modem
crtscts
lock
+pap
-chap
proxyarp
noauth
passive
192.168.10.6:192.168.10.8
debug

The file above may contain commented lines - lines starting with #. I've noticed that ppp won't make any protocol negotiation if I exclude the debug setting, for some reason. I use PAP for authentication and not CHAP, as may be concluded by the content of the file above. My PAP file - /etc/ppp/pap-secrets - looks similar to this:

# Secrets for authentication using PAP
# client    server    secret    IP-address
"user"    "wap"    "password"    192.168.10.8

Of course, a user defined in pap-secrets must be defined in the system as well. That is - the user name found in pap-secrets shall exist in /etc/passwd as well. The password of the user shall be the same in pap-secrets as in you regular authority system (/etc/passwd and /etc/shadow) - I haven't been able (had the time) to verify this. Needless to say perhaps, but remember that the password in /etc/shadow is encrypted and shall, if needed, be changed by the use of the command passwd and not edited by hand...

Start-up order:

To start-up all services needed for Kannel to serve you (or your friends) some wml-content, I recommend you to start them in the following order (httpd - apache - shall be running of course):

# First, load support for your ISDN board:
modprobe hisax type=36 protocol=2
# Then restart the mgetty...:
killall -HUP init
# Then start you kannel wap gateway (both the
# bearerbox and the wapbox):
/etc/rc.d/init.d/kannel start

Alternative Start-up:

In the Start-up order section above, it is presumed that the kernel's ISDN board support is compiled as modular support. To make it easier having all services and daemons started just by rebooting your machine, make a new kernel with ISDN support included (a description of how to make the new kernel is outside scope of this page). Also, in the used runlevel configuration directories, create symbolic links to the kannel start script. Inittab takes good care of itself and need no more attention than already given above if implementing this way.

# Make the symbolic links to kannel's start script in the corresponding
# runlevel start directories.
# I'm only using kannel in the runlevels 3 and 5 (As defined in RedHat).
cd /etc/rc.d/rc3.d
ln -s ../init.d/kannel S86kannel
cd ../rc5.d
ln -s ../init.d/kannel S86kannel

Test your WAP Gateway - emulator:

The WAP Gateway shall be running, started as described in the Start-up order section above.

If you haven't already downloaded a WAP emulator, download one from Nokia WAP forum to your second machine, preferrably running Windows (I won't dive too deep into any religious discussion about OS's here) of some sort... I'm using Nokia's Mobile Internet Toolkit Version 3.0, which has quite a few upsetting flaws - but it's definitely cheaper to use than calling repeatedly with my GSM phone.

When downloading the emulator remember to download a phone model as well. It works better than the plain vanilla out-of-the-box emulator. To give a brief idea of what to put on your WAP Gateway, I've extended the scope quite a bit. Details about the extension comes further down.

My WAP start page is pretty small. It shall be located in your apache servers' DocumentRoot path (have a look in your apache setup file for the value of your DocumentRoot: grep DocumentRoot /etc/httpd/conf/httpd.conf), in my case /var/www/html (standard). I gave the file the exciting name index.wml (you can download it here):

<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//Dtd WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
    <card id="Kort1" title="Mike's WAP-site">
        <p align="center">
        <br/>
        Light my fire!
        </p>
        <br/>
        <p align="center">
        <a href="http://192.168.10.6/lampor.wml">Light switches</a>
        <a href="#Kort2">About</a>
        <br/>
        </p>
    </card>
    <card id="Kort2" title="About">
        <p>
        Mike Bjorklind
        Ubbhult Lillhult 1
        430 64 Hällingsjö
        +46 (0)733 123461
        </p>
        <br/>
        <p align="center">
        <a href="#Kort1">First page</a>
        </p>
    </card>
</wml>

Under the settings menu, select the device (model) you downloaded. Under settings, set the connection profile to "Direct HTTP connection" and in the "Toolkit Preferences", change (or create - I don't remember) the connection type "WAP gateway connection" where you state your Linux-box IP address as gateway address, in my case 192.168.10.6, "Connection-Less" on port 9200 (the only possible selections here are connection-less and connection-oriented because Kannel doesn't support secure connections yet), a gateway timeout of 2000 msec and the URI of your WAP home page (select "Use this page:") in the Linux machine, in my case http://192.168.10.6/index.wml

Now, fire up the 6210 (or your model selection...) emulator and watch it showing the index.wml page (In the screenshot of the emulator below, "lampor" is Swedish for lights - replaced with "Light switches" in current version):

I've noticed that the emulator, now and then among other peculiarities, doesn't manage to contact the WAP Gateway.

The hilighted link "Lampor" in the screenshot above will be explained further down since it's part of the extension I mentioned above.

Test your WAP Gateway - Nokia 3330, Nokia 5210, Nokia 6210, Ericsson T68:

The WAP Gateway shall be running, started as described in the Start-up order section above.

The Nokia 6210 shall have the settings below - select the Services menu. In connection-settings-edit set the following (save under a new, or overwrite an existing connection):

Homepage:            http://192.168.10.6/index.wml
Connection type:     Continuous
Connection security: Off
Bearer:              Data
Dial-up number:      <your fixed-line ISDN number>
IP address:          192.168.10.6
Authentication type: Normal
Data call type:      ISDN
Data call speed:     9600
User name:           <user>
Password:            <password>

Nokia 3330, Nokia 5210 and Ericsson T68 shall have settings corresponding to the settings above. All the different models does not necessarily have corresponding names for the settings - but with some smart guessing, you're likely to find the parameters in your mobile model.

When having set up and activated the connection, go to the Services menu and select "Home". This will place an ISDN Data call towards your Kannel WAP Gateway and - cross your fingers - hopefully the connection is set up as expected. If not - walk through the preceeding parts carefully all over again.

Test your WAP Gateway - Ericsson R320s:

The WAP Gateway shall be running, started as described in the Start-up order section above.

The Ericsson R320s shall have the settings below (Ericsson's WAP setting is a bit more confusing than necessary, I think) - select the WAP Services menu. In WAP Settings set the following (save under a new, or overwrite an existing connection):

Homepage:            http://192.168.10.6/index.wml
Show Images:         Either On or Off (It doesn't make any difference)
Connection type:     Continuous
Access Type:         GSM Data
Response Timer:      90 Seconds
Service Centre:      NONE (Don't enter anything here)
Phone Number:        <your fixed-line ISDN number>
Dial Type:           ISDN
User ID:             <user>
Password:            <password>
Inactive Timeout:    300 Seconds
User ID:             <user>
Password:            <password>
IP Address:          192.168.010.006
SMS Adress:          NONE (Don't enter anything here)

When having set up and activated the connection, go to the Services menu and select "Home". This will place an ISDN Data call towards your Kannel WAP Gateway and - cross your fingers on the other hand - hopefully the connection is set up as expected. If not - walk through the preceeding parts carefully all over again.

WAP Gateway - extended scope; RF controlled mains voltage devices:

Why would you like to set up a WAP Gateway in your house? A fully valid question indeed! My excuse is that I'm fed with searching for cheap, working remote control devices - such as X10 which is really interesting but still too expensive in Sweden, where I live (too many middlemen want to fill their greedy pockets with profits made on the device's journey to my home).

My goal was to redesign an existing RF remote control device that I bought a long time ago. Recently I found that my local hardware store (Clas Ohlson) provided a later model of the one I already had and couldn't resist buying one - to see if it was compatible.

It came packaged with one transmitter and one receiver unit capable of switching 220 V, 10 A - priced at around USD 19.

It matches my existing remote in all aspects except that they'd added dimming functionality to my previous OFF-buttons (they've redesigned the receivers) making the new "toggle" receivers listen only at my previous "ON"-button - Hmmm... I can live with that!

Never the less - The design I added to the transmitter is the one drawn below:

I like using veroboard, which I also bought at Clas Ohlson. An old, full protocol 25-lead Male-Female cable came in handy - I just cut off the female end and replaced it with my dongle, the one shown above. In the picture below you can see how I, non-intrusively, added a 10-pin header socket to the remote transmitter (maybe Clas Ohlson could ask their supplier for a ready made dongle to plug straight into a parallel port of a PC? I mean - if youre not using the port for printing, why not put it at work as an intelligent remote instead?).

The dongle plugged into the remote:

The inside of the converted transmitter:

The dongle and the mating header, inside the remote:

My new remote - with almost infinite range (everywhere (?) on this planet where there is a GSM net):

To deal with the parallel port from my WAP session towards the Kannel WAP Gateway, from inside Linux, I made a wml page - lampor.wml - as mentioned above. In this page I put (hardcoded for now - will be soft controlled from another, future WAP page, later) my four button-pairs (ON and OFF for A through D) and pre-selected OFF (ivalue="2") for them all. Since I couldn't make the method="get" to work the first time i tried, I implemented a method="post" (read from stdin) instead.

So - first the code for the wap page lampor.wml (my private net URI is http://192.168.10.6/lampor.wml and the file may be downloaded here):

<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
    <card>
        <p>
        Te-ceremoni:
        <select name="A" ivalue="2" multiple="false">
            <option value="1">ON</option>
            <option value="0">OFF</option>
        </select>
        Piedestal:
        <select name="B" ivalue="2" multiple="false">
            <option value="1">ON</option>
            <option value="0">OFF</option>
        </select>
        Lanternin:
        <select name="C" ivalue="2" multiple="false">
            <option value="1">ON</option>
            <option value="0">OFF</option>
        </select>
        Ej i bruk:
        <select name="D" ivalue="2" multiple="false">
            <option value="1">ON</option>
            <option value="0">OFF</option>
        </select>
        <do type="accept" label="Set switches">
            <go href="http://linux/cgi-bin/commit" method="post">
                <postfield name="A" value="$A" />
                <postfield name="B" value="$B" />
                <postfield name="C" value="$C" />
                <postfield name="D" value="$D" />
            </go>
        </do>
        </p>
    </card>
</wml> 

Then, a ncsa standard POST cruncher was borrowed (you can find it if selecting the link "C: The default scripts for NCSA httpd." on this page) and "inserted" into the C-code I'm using to interface towards the parallel port. To create a binary executable from this code, you simply go to the directory where you saved it and type "make commit" - that is, if you named your C-file commit.c of course (No - a Makefile is not necessary if only compiling one C-file).

The content of the file (you can download it here) is:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define MAX_ENTRIES 10000
#define LF 10
#define CR 13
#define microsec 1
#define millisec (1000*microsec)

typedef struct {
    char *name;
    char *val;
} entry;

void write_byte( char by )
{
    int fd;
    char buf[1];
    fd = open("/dev/port", O_WRONLY);
    /* The 888 below is dec for 0x378 (parport0) */
    lseek(fd, 888, SEEK_SET);
    buf[0] = (char) by;
    write(fd, buf, 1);
    close( fd );
    /* Found out that my receivers have a weak hearing... */
    usleep( 400 * millisec );

    fd = open("/dev/port", O_WRONLY);
    lseek(fd, 888, SEEK_SET);
    buf[0] = (char) 0;
    write(fd, buf, 1);
    close( fd );
}

void getword(char *word, char *line, char stop)
{
    int x = 0,y;

    for(x=0;((line[x]) && (line[x] != stop));x++)
        word[x] = line[x];

    word[x] = '\0';
    if(line[x]) ++x;
        y=0;

    while(line[y++] = line[x++]);
}

char *makeword(char *line, char stop)
{
    int x = 0,y;
    char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));

    for(x=0;((line[x]) && (line[x] != stop));x++)
        word[x] = line[x];

    word[x] = '\0';
    if(line[x]) ++x;
        y=0;

    while(line[y++] = line[x++]);
    return word;
}

char *fmakeword(FILE *f, char stop, int *cl)
{
    int wsize;
    char *word;
    int ll;

    wsize = 102400;
    ll=0;
    word = (char *) malloc(sizeof(char) * (wsize + 1));

    while(1) {
        word[ll] = (char)fgetc(f);
        if(ll==wsize) {
            word[ll+1] = '\0';
            wsize+=102400;
            word = (char *)realloc(word,sizeof(char)*(wsize+1));
        }
        --(*cl);
        if((word[ll] == stop) || (feof(f)) || (!(*cl))) {
            if(word[ll] != stop) ll++;
            word[ll] = '\0';
            return word;
        }
        ++ll;
    }
}

char x2c(char *what)
{
    register char digit;

    digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
    digit *= 16;
    digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
    return(digit);
}

void unescape_url(char *url)
{
    register int x,y;

    for(x=0,y=0;url[y];++x,++y) {
        if((url[x] = url[y]) == '%') {
            url[x] = x2c(&url[y+1]);
            y+=2;
        }
    }
    url[x] = '\0';
}

void plustospace(char *str)
{
    register int x;

    for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
}

int rind(char *s, char c)
{
    register int x;
    for(x=strlen(s) - 1;x != -1; x--)
        if(s[x] == c) return x;
    return -1;
}

int getline(char *s, int n, FILE *f)
{
    register int i=0;

    while(1) {
        s[i] = (char)fgetc(f);

        if(s[i] == CR)
        s[i] = fgetc(f);

        if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
            s[i] = '\0';
            return (feof(f) ? 1 : 0);
        }
        ++i;
    }
}

void send_fd(FILE *f, FILE *fd)
{
    int num_chars=0;
    char c;

    while (1) {
        c = fgetc(f);
        if(feof(f))
            return;
        fputc(c,fd);
    }
}

main()
{
    entry entries[MAX_ENTRIES];
    char c;
    register int x,m=0;
    int cl;
    unsigned int channel = 0;

    cl = atoi(getenv("CONTENT_LENGTH"));

    for(x=0;cl && (!feof(stdin));x++) {
        m=x;
        entries[x].val = fmakeword(stdin,'&',&cl);
        plustospace(entries[x].val);
        unescape_url(entries[x].val);
        entries[x].name = makeword(entries[x].val,'=');
    }

    fprintf( stdout, "Content-type: text/vnd.wap.wml\n\n");
    fprintf( stdout, "<?xml version=\"1.0\"?>\n");
    fprintf( stdout, "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\"");
    fprintf( stdout, " \"http://www.wapforum.org/DTD/wml_1.1.xml\">\n");
    fprintf( stdout, "<wml>\n");
    fprintf( stdout, "<card id=\"Kort1\" title=\"Lights status\">\n");
    fprintf( stdout, "<p align=\"center\">\n");
    fprintf( stdout, "<br/>\n");
    fprintf( stdout, "Lights were set to:<br/>\n");
    fprintf( stdout, "</p>\n");

    for(x=0; x <= m; x++) {
        c = entries[x].name[0];
        switch (c) {
        case 'A':
                channel = 1;
                if (atoi(entries[x].val) == 0)
                    channel *= 2;
                    fprintf( stdout,
                        "<p>Te-ceremoni %s</p>\n",
                        (channel==1 ? "ON" : "OFF"));
                    write_byte( channel );
                break;
        case 'B':
                channel = 4;
                if (atoi(entries[x].val) == 0)
                    channel *= 2;
                    fprintf( stdout,
                        "<p>Piedestal %s</p>\n",
                        (channel==4 ? "ON" : "OFF"));
                    write_byte( channel );
                break;
        case 'C':
                channel = 16;
                if (atoi(entries[x].val) == 0)
                    channel *= 2;
                    fprintf( stdout,
                        "<p>Lanternin %s</p>\n",
                        (channel==16 ? "ON" : "OFF"));
                    write_byte( channel );
                break;
        case 'D':
                channel = 64;
                if (atoi(entries[x].val) == 0)
                    channel *= 2;
                    fprintf( stdout,
                        "<p>Not in use %s</p>\n",
                        (channel==64 ? "ON" : "OFF"));
                    write_byte( channel );
                break;
        default:
                channel = 0;
                fprintf( stdout, "<p>Error: No data.</p>\n");
                break;
        }
    }

    fprintf( stdout, "<br/>\n");
    fprintf( stdout, "<p align=\"center\">\n");
    fprintf( stdout, "<a href=\"http://linux/index.wml\">Start page</a>\n");
    fprintf( stdout, "<a href=\"http://linux/lampor.wml\">Light switches</a>\n");
    fprintf( stdout, "<a href=\"#Kort2\">About</a>\n");
    fprintf( stdout, "<br/>\n");
    fprintf( stdout, "</p>\n");
    fprintf( stdout, "</card>\n");
    fprintf( stdout, "<card id=\"Kort2\" title=\"About\">\n");
    fprintf( stdout, "<p>\n");
    fprintf( stdout, "Mike Bjorklind\n");
    fprintf( stdout, "Ubbhult Lillhult 1\n");
    fprintf( stdout, "430 64 Hällingsjö\n");
    fprintf( stdout, "+46 (0)733 123461\n");
    fprintf( stdout, "</p>\n");
    fprintf( stdout, "<br/>\n");
    fprintf( stdout, "<p align=\"center\">\n");
    fprintf( stdout, "<a href=\"#Kort1\">First page</a>\n");
    fprintf( stdout, "</p>\n");
    fprintf( stdout, "</card>\n");

    fprintf( stdout, "</wml>\n");
}

To enable the program above to access and write to the /dev/port device, the file must have the setuid bit set (I'm aware that this may be a security issue and will elaborate on this in the future - stay tuned!). The file must also be compiled as user root, otherwise the /dev/port simply won't execute your order. To set it correctly, become root and chmod the file:

[mike @ linux cgi-bin]$ su - root
Password: *****
[root@linux /root]# cd /var/www/cgi-bin
[root@linux cgi-bin]# ls -l
total 29
-rw-r--r--    1    root    root    5700 Feb 27 23:34 commit.c
[root@linux cgi-bin]# make commit
cc    commit.c    -o commit
[root@linux cgi-bin]# ls -l
total 29
-rwxr-xr-x    1    root    root   19289 Feb 27 23:34 commit
-rw-r--r--    1    root    root    5700 Feb 27 23:34 commit.c
[root@linux cgi-bin]# chmod u+s commit
[root@linux cgi-bin]# ls -l
total 29
-rwsr-xr-x    1    root    root   19289 Feb 27 23:34 commit
-rw-r--r--    1    root    root    5700 Feb 27 23:34 commit.c

WAP Gateway - extended scope; IR controlled devices:

My goal was to design an IR remote control device to control all the IR controllable devices in my living room. Since I've been kept busy with other things, I asked my good friend Nils Hammar if he could put the device together. Nils started off from the simple devices found on Karsten Scheibler's & Christoph Bartelmus' LIRC homepage (transmitter and receiver) and came up with a solution as shown in the schematics below. All components except the RJ-11 headers, cables and connectors were bought from ELFA and are standard components.

Total price for the kit is around USD 15, excluding connectors, box and cables.

The device's signalling is connected to my Linux machine's 9-pin standard serial port and an old AC/DC adapter is used for voltage supply. All incomming IR signalling is interpreted by the standard LIRC software which also controls all IR output.

I won't go too deep into details about the components used in this solution since it is somewhat outside the scope. I'll focus more on the resulting solution and how it may be utilised. I can explain, though, that the reason for having a stabiliser (L78S05) each per receiver and transmitter is to minimise the crosstalk between the two. Otherwise the receiver tries decoding what is transmitted while transmitting. A much more sophisticated solution would disregard what's transmitted, at the receiving end. This will never happen in my solution since the solution drawn below works good enough for me.

I use veroboard for this device as well. I had an old 10 meter long, 4-lead phone extension cable which I'm using between the serial port and the device. In the picture below you can see how it's all connected. The cable may be exchanged for a shorter one just by unplugging the long one and plugging in a new one, if necessary. It may be easier relocating the device physically when programming new remotes with LIRC since the programming procedure is highly interactive in terms of giving each programmed IR sequence a name by keying it in on the linux machine's keyboard.

The boxed LIRC device ended up looking like this - receiver to the left and transmitter to the right:

The 9-pin DSUB for the serial connection looks like this:

As you can see, the receiver end also has the two indicator LEDs to indicate activity in either receiving or transmitting mode. I haven't set up any "learning" mode indicator or such from LIRC to the device since some IR code simply won't let itself be learned so easily. I'll come back to that problem further down.

To enable LIRC support in linux, download the LIRC software (I downloaded lirc-0.6.5.tar.gz - a tarball) from LIRC to my linux machine. The team at LIRC recommends to update the kernel so I did:
A good hint is to update binutils first - provided you're currently using a RedHat 2.4.2 kernel - (please read about binutils at GNU first) - I updated to binutils-2.10.91.0.2-3 (the latest at the time when I downloaded it from ftp.sunet.se) followed by a download of kernel version 2.4.18 from www.kernel.org. Build a new kernel from the source you downloaded and make it current.

Compile and install LIRC according to the instructions on LIRC's installation page. Using the device shown above will need the following parameters (will be set as part of the installation - if you're "lucky" and have dialog installed) set provided you will be connecting to "com1" (in Linux we call it /dev/ttyS0) at address 0x3f8 with IRQ 4:

LIRC_DRIVER=irdeo
LIRC_PORT=0x3f8
LIRC_IRQ=4
LIRC_MAJOR=61
IRTTY=none
DRIVER_PARAMETER=com1
SOFT_CARRIER=on
TRANSMITTER=off
TIMER=65536
X11_WINDOWS=off
DEBUG=off
NO_DAEMONIZE=off
NO_LONG_CODES=off
USE_SYSLOG=off

An important parameter is the NO_DAEMONIZE. Don't change this - it shall be set to off.

To disable serial standard kernel driver for the UART, the command setserial shall be used:

setserial /dev/ttyS0 uart none

The /etc/lircd.conf file shall be populated with your "known" devices, either through the files that come with LIRC or recorded through your own lirc device.

To try out the LIRC device, start the daemon lircd:

lircd

To send a command through the device, use the LIRC command rc send_once:

rc send_once sonycd disc2

The command above selects CD number 2 in my SONY CD-changer CDP-C535. As can be seen in my /etc/lircd.conf file below, I have only recorded support for the SONY CD player at this moment. Next, the other gadgets I want to control are the TV set, two VCRs, a stationary MD player, a DVD player, an RDS Tuner and an AV amplifier. The lircd.conf file will have grown substantially when all gadgets are supported.

As can be seen in the listing below, all recorded codes are unique. I've tried recording the codes from my DVD player and found that it probably sends information in two bursts, not possible to record with the currect implementation in LIRC. I'm working on a modification of LIRC to record this type of remotes as well. The result from this modification will be submitted to LIRC as soon as I get time to do it.

# Copyright (C) 1999 Christoph Bartelmus
#
# You may only use this file if you make it available to others,
# i.e. if you send it to <lirc@bartelmus.de>
#
# this config file was automatically generated
# using lirc-0.6.5(irdeo) on Sun Mar 17 22:07:59 2002
#
# contributed by Nils Hammar
#
# brand: SONY
# model no. of remote control: RM-D535
# devices being controlled by this remote: 5 CD-Changer CDP-C535
#

begin remote

  name	sonycd
  bits		   11
  flags SPACE_ENC|CONST_LENGTH
  eps		   30
  aeps		  100

  header 	 2383	614
  one		 1198	602
  zero		  607	602
  ptrail	 1197
  gap		45022
  min_repeat	    3
  toggle_bit	    0


      begin codes
          musicscan	0x00000000000001E8
          continue	0x00000000000005C8
          shuffle	0x0000000000000568
          program	0x00000000000007C8
          discskip	0x00000000000003E8
          disc1		0x0000000000000018
          disc2		0x0000000000000418
          disc3		0x0000000000000218
          disc4		0x0000000000000618
          disc5		0x0000000000000118
          1		0x0000000000000008
          2		0x0000000000000408
          3		0x0000000000000208
          4		0x0000000000000608
          5		0x0000000000000108
          6		0x0000000000000508
          7		0x0000000000000308
          8		0x0000000000000708
          9		0x0000000000000088
          10		0x0000000000000028
          11		0x0000000000000428
          12		0x0000000000000228
          13		0x0000000000000628
          14		0x0000000000000128
          15		0x0000000000000528
          16		0x0000000000000328
          17		0x0000000000000048
          18		0x0000000000000448
          19		0x0000000000000748
          20		0x00000000000004A8
          >20		0x0000000000000728
          check		0x0000000000000588
          clear		0x0000000000000788
          file		0x00000000000004C8
          time		0x00000000000000A8
          repeat	0x00000000000001A8
          erase		0x00000000000006C8
          levelfile	0x00000000000000B8
          ams_play	0x0000000000000268
          ams_pause	0x00000000000004E8
          ams_stop	0x00000000000000E8
          ams_previous	0x0000000000000068
          ams_next	0x0000000000000468
          ams_rewind	0x0000000000000668
          ams_forward	0x0000000000000168
          dsp_select	0x00000000000005D8
          dsp_direct	0x00000000000003D8
          fader		0x00000000000007D8
          lineout+	0x0000000000000248
          lineout-	0x0000000000000648
      end codes

end remote

Will be continued (Last edited June 2, 2002).

Opinions? -> Send me a mail mike @ lillhult.com