ss-hw serves as the hardware interface for SmartShelf.  It is intended to be
used by the ss-core program, but it can be run directly for development and
debugging purposes.

See the "ss-hw" stuff in ss-core/PROTO for the protocol.  Remember, "ss-core"
is really whoever or whatever decides to execute ss-hw--- it only sees its own
stdin and stdout, which can easily be connected to your tty.  For all it cares
it could be running as an Internet service care of ucspi-tcp, netcat, or inetd!

Edit ss-hw/main.c to change which "devices" correspond to the pressure sensor,
the RFID tag reader, and the ss-core program.

The SmartShelf core should normally be connected to stdin and stdout:
    fd_init(&user, "stdin/stdout", STDIN_FILENO, STDOUT_FILENO);

The pressure sensor connects to the serial port:
    serial_init(&pressure, "/dev/ttyS1", CS8, 0, 0, B9600, 0, 0);
Change these parameters if you need different serial line settings, such as a
different device node for the serial port, different parity settings, and so on.
The pressure sensor can also reasonably be connected to the misc/randpres
program.
    child_init(&pressure, "misc/randpres 500", environ, O_RDONLY);
But first be sure to type "make misc/randpres" to generate the program from
source code.  randpres takes a single (optional) delay argument.

The RFID tag reader also connects to the serial port.
    serial_init(&rfid, "/dev/ttyS0", CS8, 0, PARENB, B38400, 0, 0);
But it can also be connected to null using null_init().  It's also possible to
connect it to the misc/hex program in order to log everything SmartShelf tries
to send to the reader.  Be sure to redirect the output thusly:
    child_init(&rfid, "misc/hex > log", environ, O_WRONLY);
It's certainly possible to use this mechanism to connect to a sophisticated
RFID tag reader emulation program.  I might just write one...

null_init() has only one parameter, the device_t*.  It creates a device that
never produces any output and ignores all data sent to it.  This is useful to
test portions of the program in isolation.  Due to weaknesses in the
implementation, null_init() might not always work correctly.

fd_init() has four parameters:
    fd_init(device_t* dev,  /* Device structure.                             */
            char* path   ,  /* (Fake) filename to associate with the device. */
            int input_fd ,  /* File descriptor from which to read data.      */
            int output_fd)  /* File descriptor to which to send data.        */
input_fd and output_fd can be -1 to indicate that the device is read- or write-
only.  They can also have the same value (i.e. be connected to the same file or
socket or device node).

The parameters for serial_init() are as follows:
    serial_init(device_t* dev,       /* Don't touch this...                  */
                char* path   ,       /* Path to the serial device node.      */
                int data_bits,       /* CS5, CS6, CS7, CS8.                  */
                int stop_bits,       /* 0: 1 stop bit; CSTOPB: 2 stop bits.  */
                int parity   ,       /* 0: no; PARENB: enabled; PARODD: odd. */
                int baud_rate,       /* B2400, B9600, B57600, B115200, etc.  */
                int sw_flow_ctrl,    /* 0: off; IXON | IXOFF: on.            */
                int hw_flow_ctrl)    /* 0: off; CRTSCTS: on.                 */
See termios(3) for more details on the meaning of these flags.

child_init() has four parameters.
    child_init(device_t* dev,   /* Device struct to configure.               */
               char* cmdline,   /* Command line to pass to `/bin/sh -c'.     */
               char** env   ,   /* Environment variables.                    */
               int mode     )   /* O_RDONLY, O_WRONLY, or O_RDWR.            */
`cmdline' can contain arguments, variable substitutions, redirections, pipes,
etc., as it is passed to /bin/sh.  The `env' parameter is typically set to
`environ', unless the program needs a customized environment.

 vim: set ts=4 sts=4 sw=4 tw=80 et:
