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

void initstdin();
int openserial(char *port);
int stripcr(char *buf);
int strip2nl(char *buf);
int stripnl(char *buf);

int main()
{
    int phone_fd, keypad_fd;
    char inbuf[1025];
    char keybuf[1024];
    char *keyptr = keybuf;
    char key;
    char cmdbuf[1024];
    int starcount = 0;

    fd_set ready;
    int ready_max;
    struct timeval tv;

    int i;

    //initstdin();

    inbuf[0]=0;

    phone_fd = openserial("/dev/ttyS3");
    keypad_fd = openserial("/dev/ttyS2");

    do 
    {
        FD_ZERO(&ready);
        FD_SET(phone_fd, &ready);
        FD_SET(keypad_fd, &ready);
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        
        ready_max = phone_fd > keypad_fd ? phone_fd : keypad_fd;
        select(ready_max+1, &ready, 0, 0, &tv);
        
        if (FD_ISSET(phone_fd, &ready))
        {
            i = read(phone_fd, inbuf, 1024);
            if (i > 0)
            {
                inbuf[i] = 0;
                stripcr(inbuf);
                strip2nl(inbuf);
                printf("%s",inbuf);
                tcdrain(STDOUT_FILENO);
            }
        }

        if (FD_ISSET(keypad_fd, &ready))
        {
            i = read(keypad_fd, &key, 1);
            if (i == 1)
            {
                if (key>='0' && key <='9')
                {
                    *keyptr++ = key;
                    printf("%c",key);
                    tcdrain(STDOUT_FILENO);
                    starcount = 0;
                }
                else if (key == '#')
                {
                    *keyptr=0;
                    keyptr = keybuf;
                    printf("\n");
                    tcdrain(STDOUT_FILENO);
                    sprintf(cmdbuf,"ATDT%s",keyptr);
                    modem(phone_fd,cmdbuf);
                    starcount = 0;
                }
                else if (key == '*')
                {
                    printf("\n");
                    tcdrain(STDOUT_FILENO);
                    keyptr = keybuf;
                    starcount++;
                    if (starcount == 2)
                    {
                        modem(phone_fd,"ATH");
                    }
                    else if (starcount == 3)
                    {
                        modem(phone_fd,"ATZ");
                    }
                    else if (starcount == 4)
                    {
                        exit(0);
                    }
                    else
                    {
                        modem(phone_fd,"AT");
                    }
                }
                else
                {
                    printf("oops: %c\n",key);
                    tcdrain(STDOUT_FILENO);
                }
            }
        }
    } while (1);
}

int modem(int fd, char *outbuf)
{
    int c;
    static char phone_linebuf[1024];
    static char *phone_linebuf_ptr = phone_linebuf;

    write(fd,outbuf,strlen(outbuf));
    write(fd,"\r\n",2);
    usleep(1000);
}


int stripcr(char *buf)
{
    char *ptr = buf;
    while (*buf != 0)
    {
        if (*buf == '\r')
        {
            buf++;
        }
        else
        {
            *ptr++ = *buf++;
        }
    }
    *ptr=0;
}

int stripnl(char *buf)
{
    char *ptr = buf;
    while (*buf != 0)
    {
        if (*buf == '\n')
        {
            buf++;
        }
        else
        {
            *ptr++ = *buf++;
        }
    }
    *ptr=0;
}

int strip2nl(char *buf)
{
    char *ptr = buf;
    while (*buf != 0)
    {
        if (*buf == '\n' && *(buf+1)=='\n')
        {
            buf+=2;
            *ptr++ = '\n';
        }
        else
        {
            *ptr++ = *buf++;
        }
    }
    *ptr=0;
}

int openserial(char *port)
{
    struct termios term;
    int fd = open(port, O_RDWR);
    if (fd<0)
    {
        printf("Could not open port %s\n",port);
        exit(1);
    }
    
    tcgetattr(fd, &term);
    term.c_lflag &= ~ICANON;
    term.c_lflag &= ~(ECHO | ECHOCTL | ECHONL);
    term.c_cflag |= HUPCL;
    term.c_cc[VMIN] = 1;
    term.c_cc[VTIME] = 0;
    
    /* Standard CR/LF handling: this is a dumb terminal.
     * Do no translation:
     *  no NL -> CR/NL mapping on output, and
     *  no CR -> NL mapping on input.
     */
    //term.c_oflag |= ONLCR;
    term.c_iflag &= ~(ICRNL | INLCR);
    term.c_iflag |= IGNCR;
    
    /* set hardware flow control by default */
    term.c_cflag |= CRTSCTS;
    term.c_iflag &= ~(IXON | IXOFF | IXANY);
    /* set 9600 bps speed by default */
    cfsetospeed(&term, B9600);
    cfsetispeed(&term, B9600);
    tcsetattr(fd,TCSANOW, &term);
    return fd;
}

void initstdin()
{
    struct termios sts;
    tcgetattr(STDIN_FILENO, &sts);
    
    /* again, some arbitrary things */
    sts.c_iflag &= ~BRKINT;
    sts.c_iflag |= IGNBRK;
    sts.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
    sts.c_cc[VMIN] = 1;
    sts.c_cc[VTIME] = 0;
    sts.c_lflag &= ~ICANON;
    /* no local echo: allow the other end to do the echoing */
    sts.c_lflag &= ~(ECHO | ECHOCTL | ECHONL);
    tcsetattr(STDIN_FILENO, TCSANOW, &sts);
}
