I need to write a program to react to the modem control lines changing in the serial port on my FreeBSD 10.3 machine. I don't want to read any data from it (there won't be any). I'm aware I can configure the port to raise (in my instance) IRQ4 when this happens, but how could my program pick up on the interrupt? Do I have to install a function pointer in the interrupt descriptor table, and if so, how? Or is there something simpler I can piggyback off?

For lack of rep I was unable to comment against plonk's helpful answer here: Viewing (monitoring) line status of a serial port

I did something similar for a parallel port in MS-DOS a while back when I made a digital readout for my milling machine, but as far as I remember that was in real mode and hooked into the IVT, which I suspect will have been simple by comparison.

(Explanation: I inherited a working but simple UPS which lacks a comms port. I figured I could 'read' the panel LEDs and beeper via electrical isolation/level conversion to the control lines in my server's serial port. Basically if anything about the machine's UPS changes from the norm, a shutdown script will be initiated. Crusty, I know, but if I can get it set up fairly quickly it'll save me £100 on a newer one.)

  • there's some IOCTLs you call on the serial port file handle to set up a signal(2) when the status changes. you won't be able to touch interrupt vectors without writing kernel code.
    – Jasen
    Jul 24 '16 at 4:18
  • @drg The UPS has had an easy life, and the battery's not long been replaced, which is why I'd resent buying another just for the comms. Were I not to know its history, though, I'd agree entirely. Biggest problem at the moment is finding an unused breadboard!
    – Superbead
    Jul 28 '16 at 17:48

As it is for a UPS, I imagine you can afford to poll the modem signals every 10 seconds or so (from freebsd tty(4)):

int state;
if(ioctl(fd, TIOCMGET, &state)...)
if(state & TIOCM_DTR)...

However, if you want to be notified immediately of changes in exactly one modem signal, namely DCD, you can set the tty flags to clear CLOCAL (see termios), then a later open() on the port will hang until modem signal DCD is active. When you lose DCD you will also get a SIGHUP.

Another mechanism is to connect one of your lines to the input RX data pin. If you pull this high for more than the appropriate character time for the speed you have set, it will generate a framing error. If you set IGNBRK=0 and BRKINT=0 then the driver will place a null byte \0 on the input queue which can unblock a pending read(), if in raw mode.

  • The 'main' LED on the UPS is steady on mains, and flashes on battery, hence a poll would either have to be frequent enough to catch the flashing early, or suffer latency to catch it eventually. Your suggestion to use DCD and open() sounds like the very thing, though - thanks very much, and to those who commented.
    – Superbead
    Jul 28 '16 at 17:44

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.