Re: ftdi_sio bug: setting two custom baud rates in a row fails

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

 



Hi Johan et al,

Now that I understand the behavior, and know how to work-around the
issue, I won't press too hard for functionality changes. But perhaps
the documentation can be improved by suggesting that the custom
divisor be set before the baud rate is set to B38400. E.g., by just
swapping the order of the instructions below.

Best,

-Ed

--- ftdi_sio.c.orig 2016-01-03 18:07:02.757626039 -0500
+++ ftdi_sio.c.patched 2016-01-03 18:08:33.647378993 -0500
@@ -1247,12 +1247,13 @@
  * this just sets alt_speed to (HI: 57600, VHI: 115200,
  * SHI: 230400, WARP: 460800)
  * ** Steps 1, 2 are done courtesy of tty_get_baud_rate
- * 3. You can also set baud rate by setting custom divisor as follows
- *    - set tty->termios->c_cflag speed to B38400
+ * 3. You can also set baud rate by setting custom divisor as follows:
  *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as
  * follows:
  *      o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
  *      o custom_divisor set to baud_base / your_new_baudrate
+ *    - set tty->termios->c_cflag speed to B38400
+ *
  * ** Step 3 is done courtesy of code borrowed from serial.c
  *    I should really spend some time and separate + move this common
  *    code to serial.c, it is replicated in nearly every serial driver


On Fri, Jan 1, 2016 at 12:53 PM, Johan Hovold <johan@xxxxxxxxxx> wrote:
> On Thu, Dec 31, 2015 at 04:38:29PM -0500, Edwin Olson wrote:
>> Hi,
>>
>> When setting custom baud rates with the ftdi_sio module using "method
>> #3" (setting the custom_divisor via TIOCSSERIAL), subsequent changes
>> to *another custom baud rate* do not  take effect.  For example, if I
>> change from baud rate 460800 (a "standard" rate) to 500000 (a custom
>> rate), it works fine. If I then go directly to 1M baud, I stay at
>> 500000 baud. If I go from 460800->500000->38400->1M, I reach 1M
>> correctly as well. Summary: it seems that transitioning from a
>> standard to a custom baud rate works; transitioning from one custom
>> baud rate to another does not (you stay in the old custom baud).
>
> Thanks for the report.
>
> Note that using ASYNC_SPD_CUST to set a custom divisor has been
> deprecated and you should be using using the TCSETS2 ioctl to set
> non-standard baudrates instead.
>
>> I think the problem is ultimately that two separate syscalls are
>> required to change a custom baud rate: set the baud rate to 38400,
>> then set the custom divisor. If one has a custom baud rate already
>> set, and then you set the baud rate to B38400, the driver immediately
>> recomputes the baud rate (using the "old" custom divisor). In other
>> words, it looks like you're trying to set a "new" custom baud rate,
>> but using the old custom divider. When the application then tries to
>> set the custom divider, the ftdi_sio driver sees that the baud rate
>> isn't 38400 and so ignores it. This logic is near line 1271:
>>
>> 1271 if (baud == 38400 &&
>> 1272             ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
>> 1273              (priv->custom_divisor)) {
>> 1274                 baud = priv->baud_base / priv->custom_divisor;
>> 1275                 dev_dbg(dev, "%s - custom divisor %d sets baud
>> rate to %d\n",
>> 1276                         __func__, priv->custom_divisor, baud);
>>
>> I think that a reasonable solution is to remove the condition that
>> baud==38400.
>
> No, the custom divisor should only be used when the speed is set to
> 38400 so that part is correct.
>
>> A tested work-around from user space is to first clear the
>> custom_divisor, then set 38400 baud, then reset the custom divisor.
>
> Setting the new divisor and then requesting 38400 baud would also work.
>
> The current behaviour was introduced back in 2007 by commit 669a6db1037e
> ("USB: ftd_sio: cleanups and updates for new termios work") which
> started reporting back the actual baudrate used by updating the termios
> structure. That had the side-effect of a custom-divisor change not
> taking effect until 38400 baud was again requested.
>
> We could consider restoring the pre-2007 behaviour of ASYNC_SPD_CUST,
> but that would prevent us from detecting that the driver selected 9600
> baud when an invalid divisor was requested.
>
> I think we should just leave this unchanged.
>
> Thanks,
> Johan



-- 
Edwin Olson
Assoc. Professor, Computer Science & Engineering
University of Michigan
http://april.eecs.umich.edu
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux