Re: Unwanted auto-assertion of DTR & RTS on serial port open

From: Mychaela Falconia <mychaela.falconia_at_gmail.com>
Date: Tue, 24 May 2022 22:47:33 UTC
Hi Warner,

Thank you for the very useful reply directly addressing the key points!

> The .init device node exists to open the device to do initialization without
> line wiggle.
> [...]
> So absent direct observations to the contrary, I'd say that opening
> the .init device will do what's desired here.

Sounds like good news - but I am also going to test it myself on
actual hardware, i.e., I'll go through the learning curve of
installing FreeBSD on a spare laptop.  For the test setup, my current
plan is to connect a USB cable from the FreeBSD machine to an FT2232D
breakout board, see if ttyU* and cuaU* devices appear as I would
expect, then connect an oscilloscope probe to DTR/RTS (first one, then
the other), set the scope to trigger on a falling edge (set the
trigger level to 2.0 V, the most common Vih spec for 3.3V logic) and
verify that no unwanted falls happen on either control signal.  Does
anyone see any problems with this plan?

Also if someone is opening a non-modem (no dial-in or dial-out
concepts) serial port for the purpose of talking to non-modem gear
(think industrial instrumentation, whatever), would it be more
"proper" to use ttyXX or cuaXX?  On Linux there is only one ttyUSBx
for each port, but with FreeBSD there is a choice - hence I'd like to
know which one is more philosophically proper.

> despite the fact that the device uses conventions that are
> not RS-232 standard conventions

But what's the alternative?  On my target GSM device I have one full
8-wire UART channel, another separate UART channel that is only TxD &
RxD, and two non-serial control lines which I would like to be able to
trigger from the connected host computer.  My current solution covers
all of these interfaces with a single FT2232D chip.  Someone could say
that I should replace this FT2232D with FT4232H (4 UART channels
instead of 2, and they don't make a 4-channel version in non-H), and
use each of the 2 extra UART channels just for its DTR (or RTS)
output, so that its control output can be independently wiggled by
opening that separate "serial" port.  But this solution would have
negatives for both power efficiency and developer-user convenience:

* Power: FT2232D eats about 30 mA, 'H' chips (FT2232H and FT4232H) eat
about 70 mA; both would be coming from the same USB VBUS.

* Convenience: it just so happens that the second UART channel on my
GSM device (the one that's data leads only) is the debug/development
interface, hence it naturally groups together with the two boot control
signals I have overlapped onto its otherwise unused DTR & RTS.  My
command line tools already make use of this grouping, operating on a
single /dev/ttyUSBx port for both UART communication and boot control.
Having two more /dev/ttyUSBx devices that aren't UART channels at all,
but exist only so that opening one or the other will cause one or the
other boot control signal to be asserted, would be no less ugly than
my current "crime" of violating RS-232 canons.

> (though most of them are somewhat
> dated, I'll admit, given the near total lack of modems today).

But my GSM device is in fact a modem - or rather a cellphone handset
with built-in modem functionality.  Those two separate UART channels I
just referred to?  The first 8-wire full UART presents the good old AT
command interface, you could dial out CSD calls through it, whereas
the second UART channel (the one with repurposed DTR & RTS) is the
special one that is totally un-modem-like.  So there you have it: a
very traditional modem serial channel *and* and a very un-modem-like
UART on the two channels behind the same USB device...

> It's hard to
> support both legacy devices and innovative devices without breaking
> somebody by default, and there's not been a ground-swell to change
> the defaults as of yet so it's rather favored the archaic traditions out
> of inertia.

Oh, I am *not* asking you or Linux maintainers or anyone else to
change any defaults!  The default is pretty much unchangeable at this
point and I am totally fine with this fact of life - instead I was
merely asking to make it possible to have a special override for
custom devices like mine.  You as in FreeBSD have finally got it right,
it seems - my deepest gratitude!  But Linux kernel maintainers are
still refusing to budge, hence I am gearing up for another round of
battle with them.

Needless to say, going to battle against Linux kernel maintainers is
no trivial matter, hence I need to gather all of my ammo first.  I
will need to personally test and verify that the feature works
correctly in FreeBSD, and assuming that it does work, then present
this evidence to Linux stonewallers.

Also while I have your attention: what's the procedure for adding
support for non-standard USB VID:PID device IDs to the uftdi driver in
FreeBSD?  I got a block of USB IDs officially allocated to me by FTDI,
and I am programming the FT2232D EEPROM on my boards with a custom USB
ID specifically to prevent special-feature-lacking drivers (those that
lack the ability to suppress auto-assertion of DTR & RTs on open) from
binding to it.  Because Linux does not have a feature like CNO_RTSDTR
in FreeBSD, and more fundamentally, it lacks the .init devices that
constitute a prerequisite for this feature addition, my idea has been
to use the custom USB device ID as the controlling mechanism for the
special feature.  The ftdi_sio driver in Linux has a table of supported
device IDs (a long and always growing table, naturally), and this table
allows associating special "quirks" with particular device IDs.  Hence
using such a device quirk seemed most natural to me, and this solution
is the one I use personally on my own system, with my own local patch.

When I start shipping FC Venus development boards and later complete
end user phones with this circuit in them, they will ship with the
USB device ID set to 0403:7152 instead of FTDI-generic 0403:6010.  For
as long as those obstinent Linux gatekeepers^Wmaintainers keep refusing
my patch adding quirked support for this new USB ID, it would be better
for unpatched Linux to not recognize my device at all, than "support"
it in a broken manner with any open of the second UART driving a hard
reset.

But for FreeBSD, given that your OS is better in this regard and
already has the necessary fundamental feature, what should we do here?
At the minimum, we would need to teach FreeBSD uftdi driver that
0403:7152 is a USB device it should bind to, and that it's actually an
FT2232D, unless the driver already figures out the latter part on its
own like the Linux driver does.  But would it also be possible to
teach the uftdi driver in FreeBSD about the special quirk?  In other
words, would it be possible to teach the uftdi driver that if it sees
USB ID 0403:7152, then for Channel B (but not for Channel A!) it
should automatically set the CNO_RTSDTR flag - or is it too much to
ask for?

CeDeROM <cederom@tlen.pl> wrote:

> some devices use those lines to power
> (i.e. Metex Multimeters) and it would be nice to set them to constant
> 0 (that results in high voltage output on the pins right?) :-)

The mapping is:

logically negated  = RS-232 -12V = LVCMOS high
logically asserted = RS-232 +12V = LVCMOS low

The LVCMOS column refers to the interface between the UART chip and
the RS-232 level shifter, or between the USB-serial chip and the end
application as more common nowadays.

> I have question: if the option is CNO_RTSDTR then application switch
> could be also -nortsdtr not -rtsdtr ? With -rtsdtr switch I would
> think this option is enabled. With -nortsdtr I am sure this option is
> disabled :-)

Given the unavoidable problem of negatives and the desire to avoid
making it even worse with double negatives, the folks who implemented
this recent feature addition in FreeBSD settled for a somewhat
inverted sense between the underlying termios flag and stty front end:

stty rtsdtr means CNO_RTSDTR flag is NOT set (default)
stty -rtsdtr means CNO_RTSDTR flag is SET (opposite of default)

M~