tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Two likely small bugs in ucom and ftdi



I have this USB FTDI device:

uftdi0 at uhub1 port 6 configuration 1 interface 0
uftdi0: FTDI (0x403) FT232R USB UART (0x6001), rev 2.00/6.00, addr 16
ucom0 at uftdi0 portno 1

Due to some device with a serial port I might receive in the future, I
wanted to test if I could use the ftdi at 2.000.000 bps.

I found two problems:

$ sudo stty -f /dev/ttyU0  2000000
stty: tcsetattr: Invalid argument

I think it should work, since from what I glean from the driver in
-current, the FTDI's clock is 3.000.000 Hz so it would end up with a
clock divisor of 1,5, and it is specifically mentioned in the driver
that it should work (albeit as a special case; more on that later).

Strangely enough, if you try stty again it doesn't complain, and stty's
output even seems to confirm that the desired speed was set.  (I was
keeping the port open between stty commands)

$ sudo stty -f /dev/ttyU0
speed 2000000 baud;
lflags: echoe echoke echoctl
oflags: onocr onlret
cflags: cs8 -parenb

I think that is because of this code in /sys/dev/usb/ucom.c:

1138	/* And copy to tty. */
	tp->t_ispeed = 0;
	tp->t_ospeed = t->c_ospeed;
	tp->t_cflag = t->c_cflag;

	if (sc->sc_methods->ucom_param != NULL) {
		error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno,
		    t);
		if (error)
			goto out;
	}

It should do the first part ("copy to tty") last, if there was no error
in actually setting the speed.

Then I discovered that the -current code allows a lot higher baud rates
than 9.3 does (which has uftdi.c rev 1.70). But before I realised
that, I had already noticed the following in rev 1.76. It comments:


595	 * When the divisor is 1 a special encoding applies:  1.0 is encoded as
	 * 0.0, and 1.5 is encoded as 1.0.  The rounding logic above has already
	 * ensured that the fraction is either .0 or .5 if the integral is 1.

I think the comment about rounding refers to this:

569	divisor = (clk << 4) / speed;
	if ((divisor & 0xf) == 1)
		divisor &= 0xfffffff8;

but I think (because 'divisor' is effectively a fixed-point fraction
with 4 fractional bits) that the condition should be

	if ((divisor & ~0xf) == 0x00000010)
or
	if ((divisor >> 4) == 1)

I can't currently test these changes because I don't have said hardware
yet (a Mega-65), but do they look reasonable to make?

-Olaf.
-- 
___ "Buying carbon credits is a bit like a serial killer paying someone else to
\X/  have kids to make his activity cost neutral." -The BOFH    falu.nl@rhialto

Attachment: signature.asc
Description: PGP signature



Home | Main Index | Thread Index | Old Index