Solved [Solved] [Workaround found] Problems with serial I/O

I seem to be having a mental block, about getting serial I/O to work under FreeBSD. Usually, this kind of stuff is really easy, but I'm doing something wrong.

My end goal is to connect a home automation system (UPB) to my FreeBSD server. That is done via a 4800 baud serial line, using only four wires (ground, TD, RD, and DTR, which the UPB gadget only needs to suck power from). I know the hardware works: I can speak to the UPB gadget using Windows (running in a VMware VM on my Mac), and I can even talk to it "directly" (without software, with just a terminal emulator) using HyperTerminal on Windows. So I connect it to the serial port on my FreeBSD server, and try using cu to talk to it, and it doesn't work at all: no bytes going in or out.

Time to simplify: I simply replaced the hardware device with a loopback adapter, which bridges pins 2 and 3 (TD and RD). I expect to see every character I type to be echoed to the screen. Now comes the amazing part: it still doesn't work, nothing happens! This is stupid, talking to a loopback wire simply has to work. So I decided to instead try it on my Mac using the console, and the exact same hardware that worked under Windows (remember, Windows was in a VM on the Mac), and lo and behold, cu doesn't work there either. So it seems that I have some mental block about using serial I/O on FreeBSD (and friends, after all the Mac is a close relative).

EDIT: See message from 20130109 below; it works fine under MacOS, if you just install the correct driver.

Here are the details. The server in question is vanilla PC hardware, an Intel Atom MoBo motherboard with two serial ports:
Code:
# uname -a
FreeBSD house.lr.los-gatos.ca.us 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan  3 07:15:25 UTC 2012 root@obrian.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386
# dmesg | egrep "uart|sio|tty|cua"
uart0: <16550 or compatible> port 0x3f8-0x3ff irq 4 flags 0x10 on acpi0
uart1: <16550 or compatible> port 0x2f8-0x2ff irq 3 on acpi0

Output from cu, before running cu, the cu command line, and the cu variables:
Code:
# stty -a -f /dev/cuau1
speed 9600 baud; 0 rows; 0 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
	-echoprt -altwerase -noflsh -tostop -flusho -pendin -nokerninfo
	-extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel -ignbrk
	brkint -inpck -ignpar -parmrk
oflags: opost onlcr -ocrnl tab0 -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl clocal -cstopb -crtscts -dsrflow
	-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
	eol2 = <undef>; erase = ^?; erase2 = ^H; intr = ^C; kill = ^U;
	lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q;
	status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;
# cu -s 4800 -l /dev/cuau1 dir
Connected
~v
beautify true
baudrate 4800
dialtimeout 60
eofread
eofwrite
eol
escape ~
exceptions
force \^P
framesize 1024
host cu4800
log /var/log/aculog
phones
prompt \^J
raise false
raisechar \^@
record
remote
script false
tabexpand false
verbose false
SHELL /bin/ksh
HOME /root
echocheck false
disconnect
tandem true
linedelay 0
chardelay 0
etimeout 0
rawftp false
halfduplex false
localecho false
parity none
hardwareflow false
linedisc 0
direct true

Here is the output from stty while cu is running (just to show you that the serial line discipline is still set reasonably, look at clonal and crtscts), collected from a separate terminal window:
Code:
# stty -a -f /dev/cuau1
speed 4800 baud; 0 rows; 0 columns;
lflags: -icanon -isig -iexten -echo echoe -echok echoke -echonl echoctl
	-echoprt -altwerase -noflsh -tostop -flusho -pendin -nokerninfo
	-extproc
iflags: -istrip -icrnl -inlcr -igncr ixon ixoff ixany imaxbel -ignbrk
	brkint -inpck -ignpar -parmrk
oflags: -opost onlcr -ocrnl tab0 -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl clocal -cstopb -crtscts -dsrflow
	-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
	eol2 = <undef>; erase = ^?; erase2 = ^H; intr = ^C; kill = ^U;
	lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q;
	status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;

I have a display box on the serial port, and it shows the following: When cu starts, it correctly turns on DTR and RTS, but it never transmits anything on TD. Note that the serial line is set for no hardware flow control. Using "~#" in cu, I can transmit a break, and that actually makes the TD line toggle correctly. I have verified with a probe that nothing is being transmitted out the transmit pin.

And here is another weirdness: suspecting that hardware flow control may be on after all, I also bridged pins 4 and 5 (CTS and RTS) and pins 6/8/20 (DTR, DSR and CD). Then I decided to suspect cu, and tried minicom.py, which is an example program that comes with the python serial package. It has the nice feature that one can toggle RTS and DTR under keyboard control. The funky thing is the following in its output (as a response to Ctrl-T Ctrl-I to give information):
Code:
# miniterm.py /dev/cuau0 4800
--- Miniterm on /dev/cuau0: 4800,8,N,1 ---
--- Quit: Ctrl+]  |  Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---

--- Settings: /dev/cuau0  4800,8,N,1
--- RTS: active    DTR: active    BREAK: inactive
--- CTS: inactive  DSR: inactive  RI: inactive  CD: inactive
--- software flow control: inactive
--- hardware flow control: inactive
--- data escaping: raw  linefeed: CR/LF
Note that it claims that CTS, DSR and CD are all inactive, even though CTS is connected to RTS, and DSR/CD are connected to DTR, and with the LEDs on the breakout box I can clearly see that they are all active.

Two more things I checked: The results on both serial ports cuau0 and cuau1 are exactly the same. As is the behavior on my Mac (using a no-name brand USB serial adapter, which works fine when running Windows in a VM on that very same Mac).

What gives? Have I completely forgotten how to use serial I/O on BSD-like operating systems? What am I doing wrong?
 
Re: Problems with serial I/O

Update: I had some spare time, and no good ideas on what to try next, so I decided to waste some time on doing something random. So I plugged another no-name-brand USB serial converter into my FreeBSD server, plugged the serial loopback in, and lo and behold: it works great! Both with cu and with minicom.py, and at all baud rates. Then I plugged in the UPB home automation gadget, and it also works perfectly using cu. So for now I have a workaround. Here are its vital statistics from dmesg:
Code:
uplcom0: <Prolific Technology Inc. USB-Serial Controller, class 0/0, rev 1.10/3.00, addr 3> on usbus0

Nitpick: There is one tiny bug with the USB serial driver: when the last program closes the port, it forgets to release RTS and leaves it turned on; but DTR is handled correctly. Not a problem for me, since I don't use hardware flow control. I'll do more verification on that, and then post a bug report in the peripheral hardware forum.

Where does that leave the built-in serial ports on the motherboard? I know now that the overall serial infrastructure in FreeBSD works correctly (which I never doubted), and that I remember how to use stty, cu, and termios (which I had doubted). The only likely explanation that is left is that the serial hardware on my motherboard is in some fashion incompatible with FreeBSD's drivers, or simply broken. I'll try to validate that when time allows by booting a Linux distribution from a CD, and see whether that magically makes the serial ports work.

I'll change the subject line to mark that this is "solved", and once I have more debugging data, open new threads (with bug reports) in the appropriate sub forums.
 
Update: Two open questions were answered.

First: why does the Prolific USB-to-serial converter not work under MacOS? It turns out to work just excellently, if you download the correct driver for it. The driver I had under MacOS was about four years old, possibly a lot older than the actual hardware of the USB-to-serial converter. Now with the correct driver downloaded (I used the NoZAP version), it works excellently.

Second: does the motherboard hardware work at all? That was verified by booting Linux (a Knoppix CD-based distribution). And lo and behold, the serial port works fine there. So the problem is with the FreeBSD support for the 165xx serial port chip, in the particular version on my motherboard. I'll post a bug report in the appropriate sub forum soon.
 
I completely forgot to update this thread with the resolution.

In summary, when running FreeBSD 9.0 on my JetWay NF99FL Atom-based motherboard, the motherboard serial ports didn't work. Nobody knows why. A problem report was filed, and USB-serial converters used as a workaround. A few months ago, I upgraded to FreeBSD 11.0, and the serial ports work now. So the kernel code must have been fixed in the meantime.
 
Back
Top