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?


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. – Johan Myréen Aug 31 '18 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 '18 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. – Johan Myréen Aug 31 '18 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.