# Serial programming with termios



## j4ck (Mar 9, 2013)

Hi guys,

I'm trying to connect to a CISCO router using termios. I have some small problems. When I press the enter key, I get double prompts. Here is what I've done:


```
struct termios dev;
int fd = 0;
fcntl(fd, F_SETFL, FNDELAY);
tcgetattr(fd, &dev);
dev.c_lflag &= ~(ICANON | ISIG | ECHO);
dev.c_iflag &= ~(ICRNL);
tcsetattr(fd, TCSANOW, &dev);
```

And I have two threads, one for reading user input and the other one for writing and reading the port. I expect this output:


```
Router>
```

But what I get is:


```
Router>
Router>
```

And this happens all the times except for the first time. Am I missing something?

Thanks.


----------



## expl (Mar 11, 2013)

You need to post full source code. Also, there is no need for multithreading to handle user input and a serial port at same time.


----------



## kpa (Mar 11, 2013)

How about looking at the source code of cu(1) for example for inspiration?


----------



## j4ck (Mar 13, 2013)

Thank you for your answers. Here's my code:


```
int mainfd=0;
char ch[2] = {NULL};

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *write(void *)
{
    char temp;
    while(1)
    {
        temp = getchar();
        ch[0] = temp;   ch[1] = '\0';
        if(temp == '~')
        {
            printf("connection closed.\r\n");
            close(mainfd);
            pthread_exit(NULL);
        }
        pthread_mutex_lock(&mutex);
        check=write(mainfd, ch, 1);
        ch[0]='\0';
        pthread_mutex_unlock(&mutex);
    }
}

void *read(void *)
{
    char outputbuffer[10000]= {0};
    while(1)
    {
        pthread_mutex_lock(&mutex);
                outputbuffer[0]='\0';
                int charnumber=read(mainfd, &outputbuffer, sizeof(outputbuffer));
                outputbuffer[charnumber] = '\0';
                printf("%s",outputbuffer);
                outputbuffer[0] = '\0';
        pthread_mutex_unlock(&mutex);
    }
}

int main(int argc,char *argv[])
{
    struct termios options;
    static int portnum=atoi(argv[1]);

    mainfd = open_port(portnum);

    fcntl(mainfd, F_SETFL, FNDELAY);  
    tcgetattr(mainfd, &options);
    cfsetspeed(&options, speed);
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;
    options.c_cflag |= CSTOPB;

    options.c_cflag &= ~CSIZE;
    options.c_cflag |=  CS8;
    options.c_cflag &= ~CRTSCTS;
    options.c_iflag &= ~(ISTRIP|ICRNL);
    options.c_oflag &= ~OPOST;
    options.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO);
    options.c_cc[VMIN] = 1;
    options.c_cc[VTIME] = 0;
    //
    tcsetattr(mainfd, TCSAFLUSH, &options);
    pthread_t threads[2];
    pthread_create(&threads[0], NULL, write, NULL);
    pthread_create(&threads[1], NULL, read, NULL);
    pthread_exit(NULL);
}
```

My last problem solved, here's another problem; each character I type is shown with the next character I type, something like:


```
Router>

Router> // I start typing "enable" here
eRouter>neanbalbel // I continue typing
```

Any suggestions?
Thanks.


----------



## expl (Mar 13, 2013)

Ok, you should configure your local TTY not to echo user input, not to escape special combinations like ctrl+c, not to buffer input. What you want is basically to directly relay keyboard input to the serial port and only print what it sends you back.

You can also drop the multithreading and just use single thread that polls (poll()) stdin and the serial fd and handles I/O for them in order.


----------



## j4ck (Mar 14, 2013)

How can I get the current TTY a user is using? And how can I change the attributes?


----------



## expl (Mar 14, 2013)

```
struct termios mytty;

/*get current TTY settings*/
if (tcgetattr(STDIN_FILENO, &mytty) < 0)
  return 1;

/* raw input */
mytty.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);

/* 8bits per char */
mytty.c_cflag |= (CS8);

/* turn off echoing */
mytty.c_lflag &= ~(ECHO | ICANON | IEXTEN);
 
/*set new settings*/
if (tcsetattr(STDIN_FILENO , TCSAFLUSH, &mytty) < 0)
  return 1;
```


----------



## j4ck (Mar 14, 2013)

Thanks, you really helped 
Things work fine but there is still one remaining problem. I appreciate if you can help me about this one too.

After adding this code; I expect immediate output once e key is hit but the output of hitting the key is show with the next one:

```
Router>
Router>abc // While I typed "abcd". If I continue with typing "e", then the output will be "abcd" and so on ...
```


----------

