I need to synchronize an IO pin value with a write to a serial port from user space (because I wasn't yet able to do it from kernel space - see my other question). My code (leaving out error checking) is as follows:

char buf[3] = {'U','U','U'};
int fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY); // supposed to be blocking
// fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK); <-- makes no difference
FILE *f = fopen("/sys/class/gpio/gpio200/value", "w"); // the relevant IO

// set IO
fprintf(f, "1");
// send data 
write(fd, buf, sizeof(buf));
// unset IO
fprintf(f, "0");

The behavior is that the IO is quickly toggled to 1 and back at the start of the write. In other words, write() returns long before the data has been actually put on the wire.

Is there a hope here?


1 Answer 1


For tty devices, you must use tcdrain() on the file descriptor.

  • 1
    According to the kernel source code, the TCSBRK ioctl (which is invoked by the tcdrain library function), returns when the kernel buffer associated with the tty is empty. This means the last byte has been written to the hardware for transmission, but most probably the byte has not been yet been fully put on the wire. In addition, if the hardware UART has an internal buffer, several bytes may be waiting for transmission. Aug 31, 2018 at 15:28
  • cite? you should always cite the version of the kernel code you looked at, if nothing else. looks like it does to me. elixir.bootlin.com/linux/v4.18/source/drivers/tty/serial/…
    – sourcejedi
    Aug 31, 2018 at 18:02
  • Yes, it looks like I was wrong, sorry. I misread the code; the driver does indeed do a best effort to query the hardware, if the hardware supports it. Aug 31, 2018 at 19:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .