Search code examples
linuxuart

Detect serial break linux


Is it possible to detect a serial breaks and tell which serial port generated it on Linux? I've seen some solutions that generates a sigint from breaks, but I need to know which one of 2 serial ports reads the break which as far as i understand it can't be done with the sigints.


Solution

  • BRKINT will send a signal if the serial port is the controlling tty of the foreground process group. A session can have at most one controlling tty. So I don't think you need to worry about telling which port the signal is from as you can't get signals from more than one port to begin with.

    This termios stuff is ancient UNIX for the days when everyone connected to a multi-user mainframe with serial teletype terminals. Software archaeology. It wasn't meant for monitoring serial UARTs, rather so random UNIX commands that didn't know anything about serial ports could automatically exit when someone's modem hung up. vi could save the file you were editing. Hitting the 'BREAK' key on your vt102 terminal would cause the current command to exit.

    If you want to use this, I think you'll have to have two process, each one monitoring a single serial port. You'll know which port got the break based on which one got the signal. You'll have to make each process its own session leader (see setsid()) and set the serial port to the controlling tty (see TIOCSCTTY and TIOCSPGRP).

    Another method is to continuously poll the serial ports using the TIOCGICOUNT ioctl. This will give you counters for the number of break, frame, and parity errors on that port. Watch for them to increase. Of course polling is much less efficient than getting a signal and means it may take up to your polling interval before discovering the break.

    I'm not sure what your application is, but I've found trying to talk ancient and obscure RS-232 protocols with stock Linux to be problematic. Things like monitoring a bank of serial lines for BREAKs, or using a 10 μs gap between characters to signal inter-packet framing, or characters greater than 8 bits wide, etc. just don't work well. If you can do kernel programming, you can create a custom line discipline that makes these things possible. One could have a break (or framing error, or parity error) monitoring line discipline where all you have to do is call select() from userspace on your port(s) and it will signal when the monitored event occurs.