/* Ralf Ackermann, rac@iptel-now.de, 2001 */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#include <termios.h>

#define RETOUR_OK       0
#define RETOUR_ERROR    -1

int init_ser(char *ser_device);
int set_ser_param(int fd);
void flush_ser(void);
int shutdown_ser(void);
char get_1_char(void);

/* (fd == -1) shows that fd is not valid */
int fd=-1;

int init_ser(char *ser_device)
{
    /* fd is static to this module but not to be seen outside */
    fprintf(stderr, "Opening serial device: %s\n", ser_device);
    fd=open(ser_device, O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
    if (fd == -1)
    {
        fprintf(stderr, "Error opening serial device !\n");
        return (RETOUR_ERROR);
    }
    else {
        fprintf(stderr, "open returned: %d\n", fd);
        if (set_ser_param(fd) == RETOUR_ERROR) {
            fprintf(stderr, "Couldn't set serial parameters !\n");
            close(fd);
            fd=-1;
            return (RETOUR_ERROR);
        }
        else {
            /* printf("Sucessfully opened serial device !\n"); */
            return (RETOUR_OK);
        }
    }
}

int set_ser_param(int fd)
{
    /* see: man termios(3) */
    int line;
    struct termios options;

    tcgetattr(fd, &options);

#if 0
    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);
#endif

    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);

    options.c_cflag &= ~PARENB;
    options.c_cflag |= CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    /* disable hardware flow control - would be */
    options.c_cflag &= ~CRTSCTS;

    options.c_cflag |= CREAD;

    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_iflag=(IMAXBEL | IGNBRK);
    options.c_oflag=0;

    options.c_cc[VTIME]='\0';
    options.c_cc[VMIN]='\0';

    tcsetattr(fd, TCSANOW, &options);

    flush_ser();
}

void flush_ser(void)
{
    ioctl(fd, TCFLSH, 0);
}

int shutdown_ser(void)
{
    if (close(fd) == -1) {
        fd=-1;
        return (RETOUR_ERROR);
    }
    else {
        fd=-1;
        return (RETOUR_OK);
    }
}

char get_1_char(void)
{
    char recv_char;
    int r_code;

    do {
        /* wait for a char to arrive */
        r_code=read(fd, &recv_char, 1);
    }
    while (r_code != 1);

    return (recv_char);
}

int main(int argc, char **argv)
{
    unsigned char buffer;
    if (argc != 2)
    {
        fprintf(stderr, "usage: %s </dev/ttyS?> !\n");
        exit(0);
    }

    init_ser(argv[1]);
    flush_ser();

    while (1)
    {
        buffer=get_1_char();
        printf("<%02x>", (unsigned char)buffer);
        fflush(stdout); 
    }
}
