In an embedded system we use an ftdi chip FT4232HL for serial communication.
Channels 1 and 2 are unused, channel 3 is RS485, channel 4 is RS232.
The system is a kind of terminal which responds to messages
coming in via serial communication.
We previously used FreeBSD 8.2 without any problems.
With FreeBSD 10.3 we found the following situation:
1. Turn on power.
2. Wait until BIOS finishes and boot loader starts.
3. Immediately begin transmitting messages via RS485 to this device.
4. Application starts and opens /dev/cuaU2.
5. Application sees message and posts answer, but answer is not being sent.
6. Close application and outstanding characters are being sent.
7. Reopen application and all works fine.
This problem seems to only occur with RS485 at cuaU2,
*not* with RS232 at cuaU3.
If nothing is being sent before step 4 all seems ok.
With hw.usb.ucom.debug=1 I can see that ucom_outwakeup()
seems never being called in error case. The first ucom_outwakeup()
I then see comes from close().
Having put additional debug messages in ucom_get_data() and
ucom_put_data() I can see that my application tries to send
the expected response.
ioctl(UFTDIIOC_RESET_IO) after open() seems to solve that problem for me.
But I am unsure if this is a fix of a chip problem or a workaround
for a kernel/driver/locking problem (which could also come from
the upper tty layer).
Have a look at the USB traffic using usbdump tool. It will show what is going on at the lowest level.
Are you using libftdi?
Are there any other applications which use libusb to communicate with the FTDI chip instead of /dev/cuaUX ?
Created attachment 186784 [details]
3 different usbdumps
usb.err.dump - The error scenario as described in the ticket:
serial data coming in before opening /dev/cuaUx
usb.ok.dump - No serial communication before opening /dev/cuauX
usb.ioctl.dump - ioctl(UFTDIIOC_RESET_IO) after open()
I'll look into this.
I can confirm that a large change in the ftdi driver between 8.2 and 10.x was that the old code would reset the chip on open(), and now that doesn't happen. The reset was harmful for some embedded uses, such as when the chip is used in mpsse or bitbang mode.
How is your rs485 transceiver connected to the ftdi? Is the transmitter connected to #TXDEN, and if so, are you using the eeprom to reconfigure that pin from RI to TXDEN? Is the receive side squelched in hardware (as suggested in the ftdi datasheet, or otherwise) when the transmit side is active?
(In reply to Hans Petter Selasky from comment #1)
No, I am not using libftdi. (Didn't even know that it exists)
This is the only application using cuaUX.
(In reply to Ian Lepore from comment #3)
I just asked our hardware developer. Yes we use #TXDEN and have the
chip configuration in the eeprom. There is no receiver side squelch, as
we use 4 wires (full-duplex) and this is a slave device.
(The master's Tx connects to all slaves' Rx and slaves' Tx are wired
together to the master's Rx)
I spent some time debugging on this yesterday, but didn't make much progress. I find the usbdump output hard to read. I do notice in the modem status bits that the data that arrives in the failure case is interpretted by the chip as a BREAK. How the tty layer presents that to the app depends on some termios(4) settings.
I think I might get more info out of the kinds of debugging you mentioned in the original report. I'd like to see the output with hw.usb.ucom.debug=1 and hw.usb.uftdi.debug=3, plus whatever extra printfs you might have added.
The 8.2-Release driver did a RESET_SIO on every open(), and that was bad for some embedded-system uses (such as when the chip had already been put into mpsse mode and was driving certain pins as gpio outputs). I wonder if it may be sufficient to do a single reset at device-attach time to solve your problem? I'm attaching a patch to do that, could you please give it a try?
Created attachment 187009 [details]
Do a device reset at attach() time