Как использовать Termios для отправки байтов по циклу передачи данных socat

Я пытаюсь написать простую программу, которая отправляет байты по последовательному соединению. Я создал цикл передачи данных с помощью socat следующим образом:

$ socat -d -d pty pty

Это создает цикл передачи данных между /dev/pts/2 и /dev/pts/0. Когда я пытаюсь использовать termios в своей программе C для записи нескольких байтов, я успешно могу открыть последовательное соединение с помощью open(). Затем я пишу несколько байтов, используя write(), и получаю количество записанных байтов. Тем не менее, когда я слушаю противоположные стороны, я не вижу никакого результата. Я использовал их, чтобы попытаться прослушать в другом терминале:

$ cat /dev/pts/0 | xxd
$ read -r line < /dev/pts/0
$ echo $line

Я знаю, что мое соединение socat работает, потому что, когда я повторяю байты и слушаю их на другом конце, я получаю их нормально.

#define BAUD_RATE B9600
#define PORT_NAME "/dev/pts/2"

/* Serial Connection Manager */
struct termios tty;
int fd;

int main(){
  /*
  O_RDWR: read/write access to serial port
  O_NOCTTY: No terminal will control the process
  O_NDELAY: Non-blocking, returns immediately
  */
  fd = open(PORT_NAME, O_RDWR | O_NOCTTY | O_NDELAY);
  printf("%s\n", PORT_NAME);
  if (fd == -1) {
    printf("Error in opening serial port\n");
    return -1;
  }
  else
    printf("Port opened successfully\n");

  tcgetattr(fd, &tty); // get current attrs of serial port
  // raw mode of terminal driver
  //cfsetispeed(&tty, BAUD_RATE);
  //cfsetospeed(&tty, BAUD_RATE);
  cfmakeraw(&tty);

  // set additional control modes
  cfsetspeed(&tty, (speed_t) BAUD_RATE);
  tty.c_cflag &= ~CSTOPB; //1 stop bit
  tty.c_cflag &= ~CRTSCTS; //disable hardware flow control
  tty.c_cflag |= CLOCAL; //ignore modem control lines
  tty.c_cflag |= CREAD; //enable receiver

  if((tcsetattr(fd, TCSANOW, &tty)) != 0){
    printf("Error in setting attributes\n");
    close(fd);
    return -1;
  }
  else
    printf("BaudRate = %d\nStopBits = 1\nParity = Odd\n", BAUD_RATE);

  sleep(1); // wait for configuration
  tcflush(fd, TCIOFLUSH);

  char buf[3] = "abc";
  int bytes_written = write(fd, buf, 3);
  printf("Bytes written: %d", bytes_written);
  close(fd);
  return 0;
}

Я ожидал, что смогу прослушивать байты, используя $ read -r output < /dev/pts/0, и что при эхо-выводе будет отображаться «abc».

Запуск моей программы дает следующий результат:

/dev/pts/2
Port opened successfully
BaudRate = 13
StopBits = 1
Parity = Odd
Bytes written: 3

Итак, я знаю, что байты куда-то идут, так как write() не возвращает -1.


person BreakfastCalzone    schedule 17.07.2019    source источник


Ответы (1)


Ваш код отлично работает с реальными и виртуальными последовательными портами для меня.

Вам нужно обратить внимание на вывод socat:

$ socat -d -d pty pty
2019/07/18 07:55:45 socat[8144] N PTY is /dev/pts/2
2019/07/18 07:55:45 socat[8144] N PTY is /dev/pts/3
2019/07/18 07:55:45 socat[8144] N starting data transfer loop with FDs [5,5] and [7,7]

Затем слушайте на первом порту пары:

$ cat /dev/pts/2

И запустите свой код (скомпилированный с помощью PORT_NAME "/dev/pts/2"), и вы увидите abc на терминале, где вы запускаете cat.

Вы также можете попробовать подключиться к /dev/pts/2 или /dev/pts/3 с помощью minicom или любого другого терминала, который вам нравится, и вы увидите вывод:

$ minicom -D /dev/pts/2 -b 9600
person Marcos G.    schedule 18.07.2019
comment
Если я пишу байты в /dev/pts/2, разве я не могу прослушивать /dev/pts/3 для наблюдения за выводом (поскольку это соединение для передачи данных между ними)? Когда я вывожу в /dev/pts/2, я могу использовать cat /dev/pts/3, чтобы увидеть, что я вывел. - person BreakfastCalzone; 18.07.2019
comment
Кроме того, это было сделано именно так, прослушивая ОБА /dev/pts/2 и /dev/pts/3, но это все равно не сработало. - person BreakfastCalzone; 18.07.2019
comment
С minicom я вижу данные по обоим портам. Если я использую cat, я могу видеть данные только по /dev/pts/2. - person Marcos G.; 18.07.2019
comment
О, хорошо, он работает с minicom, и я вижу его только на том порту, в который не записывается (что является ожидаемым поведением). Спасибо! Не уверен, почему cat и read не работают. - person BreakfastCalzone; 18.07.2019
comment
Да, это соответствует тому, что я вижу. Я тоже не знаю, почему cat так работает. Мне это никогда не нравилось. - person Marcos G.; 18.07.2019