PLEASE NOTE: This article is obsolete or related to a discontinued product.

Relay HTTP parameters to a serial port

written by the John Crispin

The following example explains how a CGI written in C can be used to relay HTTP parameters to a serial port.

When calling the CGI, you are presented with 2 forms, that can be used to send ascii or hex data to the serial port. Once data was sent, the code will sleep for 1 second and then see if an answer was received.

This example can be tested together with the example given in Using serial ports in C.

The code should be self explainatory and it should be easy to modify it for your needs. Simply copy the compiled executable class='acmetable' to the cgi folder and browse to it.

    TTY CGI demo app    
    Copyright (C) 2006 John Crispin
    This is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    This example is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    GNU General Public License for more details.
    To have a copy of the GNU General Public License write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

#include <stdio.h>     
#include <stdlib.h>
#include <string.h>    
#include <unistd.h>    
#include <fcntl.h>     
#include <errno.h>     
#include <termios.h>   
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdarg.h>
#include <signal.h>

#include "lib_tty.h"

// the serial device that will be used by the CGI
#define TTYS  "/dev/ttyS3"

// this function is used to parse the QUERY_STRING environment variable
int read_parameter(char *name, char *value, int maxlen){
  char *pos1, *pos2;
  char *query_string = getenv("QUERY_STRING");
  int success = 0;
    pos1 = strstr(query_string, name);
      pos1 += strlen(name) + 1;
      pos2 = strstr(pos1, "&");
        *pos2 = '\0';
      if(strlen(pos1) >= maxlen){
        pos1[maxlen] = '\0';
      strcpy(value, pos1);
      success = 1;
  return success;

// the applications main function
int main(int argc, char *argv[]) {
  // the descriptor for the serial port
  int tty_fd_out;

  // buffer used for serial input/output
  char buffer[1024];
  // print out the default cgi header
  printf("Content-type: text/html\n\n");

  // print out the html header
  printf("<html>\n<head>\n<title>Serial CGI example</title></head><body>");

  // try to open the serial port
  tty_fd_out = tty_open(TTYS);
  if (tty_fd_out < 0) {
      printf ("tty open error %s\n</body>", TTYS);

  // print out the page header
  printf("<h1>Acmesystems - TTY CGI</h1>");

  // print out the html forms
  printf("<form method=get>\n");
  printf("ASCII data <input type=text name=write_ascii>");
  printf("<input type=submit value=\"Send on %s\">", TTYS);

  printf("<form method=get>\n");
  printf("HEX data <input type=text name=write_hex>");
  printf("<input type=submit value=\"Send on %s\">", TTYS);
  // if we write data, we wait for 1 second to see if we get an answer
  int wait_answer = 0;
  // are we supposed to send a ascci string to the serial port ?
  char env_write_ascii[128];
  if(read_parameter("write_ascii", env_write_ascii, 128)){
      printf("<hr>writing ascii string \"%s\" on %s<br>", env_write_ascii, TTYS);
      tty_printf(tty_fd_out, env_write_ascii);
      wait_answer = 1;
  // are we supposed to send a 32bit hex value to the serial port ?
  char env_write_hex[8];
  if(read_parameter("write_hex", env_write_hex, 8)){
      unsigned int numeric;
      printf("<hr>writing 32 bit hex data \"%s\" (%u) on %s<br>", env_write_hex, numeric, TTYS);
      sscanf(env_write_hex, "%X", &numeric);
      buffer[0] = (numeric >> 24) & 0xff;
      buffer[1] = (numeric >> 16) & 0xff;
      buffer[2] = (numeric >> 8) & 0xff;
      buffer[3] = (numeric >> 0) & 0xff;
      tty_tx(tty_fd_out, buffer, 4);
      wait_answer = 1;

  // if we have send out data, we wait for 1 second and then try to read in an answer
    memset(buffer, 0, 128);
    int count = tty_rx(tty_fd_out, buffer, 128);
    if(count != -1){
      printf("<hr>read %d bytes -> \"%s\" from %s<br>", count, buffer, TTYS);
    } else {
      printf("<hr>there was no pending data on %s", TTYS);
  // print out the html footer  
  return EXIT_SUCCESS;