Re: non-standard baud rates with Prolific 2303 USB-serial

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

 



On Fri, Mar 12, 2021 at 08:28:04PM -0500, Michael G. Katzmann wrote:
> On 3/12/21 8:44 AM, Johan Hovold wrote:
> 
> 
> Let me try that patch in the right format 8-)

That's better, but we also need a commit message and and Signed-off-by
line from you. Take a look at the general format of the patches I CCed
you on and there's some more information under Documentation/:

	Documentation/process/submitting-patches.rst

The easiest is probably to use git-format-patch and git-send-email to
prevent the patch from being corrupted (e.g. the tabs below have been
replaced by spaces).
 
> --- a/drivers/usb/serial/pl2303.c    2021-03-12 09:30:22.963992109 -0500
> +++ b/drivers/usb/serial/pl2303.c    2021-03-12 20:00:20.003526891 -0500
> @@ -188,6 +188,7 @@
>      unsigned long quirks;
>      unsigned int no_autoxonxoff:1;
>      unsigned int no_divisors:1;
> +    unsigned int alt_divisors:1;
>  };
>  
>  struct pl2303_serial_private {
> @@ -217,10 +218,12 @@
>      [TYPE_TA] = {
>          .name            = "TA",
>          .max_baud_rate        = 6000000,
> +        .alt_divisors        = true,
>      },
>      [TYPE_TB] = {
>          .name            = "TB",
>          .max_baud_rate        = 12000000,
> +        .alt_divisors        = true,

Are you sure that the TB uses the alternate encoding?

Charles, could you help us out here? Which other device types use the
alternate encoding (e.g. HX(A) or TB) if any?

>      },
>      [TYPE_HXD] = {
>          .name            = "HXD",
> @@ -618,6 +621,46 @@
>      return baud;
>  }
>  
> +static speed_t pl2303_encode_baud_rate_divisor_alt(unsigned char buf[4],
> +                                                                speed_t baud)
> +{
> +        unsigned int baseline, mantissa, exponent;
> +
> +        /*
> +         * Apparently, for the TA version the formula is:
> +         *   baudrate = 12M * 32 / (mantissa * 2^exponent)
> +         * where
> +         *   mantissa = buf[10:0]
> +         *   exponent = buf[15:13 16]
> +         */
> +        baseline = 12000000 * 32;
> +        mantissa = baseline / baud;
> +        if (mantissa == 0)
> +                mantissa = 1;   /* Avoid dividing by zero if baud > 32*12M. */
> +        exponent = 0;
> +        while (mantissa >= 2048) {
> +                if (exponent < 15) {
> +                        mantissa >>= 1; /* divide by 2 */
> +                        exponent++;
> +                } else {
> +                        /* Exponent is maxed. Trim mantissa and leave. */
> +                        mantissa = 2047;
> +                        break;
> +                }
> +        }
> +
> +        buf[3] = 0x80;
> +        buf[2] = exponent & 0x01; // LS bit of exponent
> +        buf[1] = (exponent & ~0x01) << 4 | mantissa >> 8; // 3 bits of the exponent and MS 3 bits of the mantissa
> +        buf[0] = mantissa & 0xff; // LS 8 bits of the mantissa

Please avoid c99-style comments, but perhaps the comment at the start of
function is sufficient here.

Looks great otherwise.

> +
> +        /* Calculate and return the exact baud rate. */
> +        baud = (baseline / mantissa) >> exponent;
> +
> +        return baud;
> +}
> +
> +
>  static void pl2303_encode_baud_rate(struct tty_struct *tty,
>                      struct usb_serial_port *port,
>                      u8 buf[4])
> @@ -645,6 +688,8 @@
>  
>      if (baud == baud_sup)
>          baud = pl2303_encode_baud_rate_direct(buf, baud);
> +    else if (spriv->type->alt_divisors)
> +                baud = pl2303_encode_baud_rate_divisor_alt(buf, baud);
>      else
>          baud = pl2303_encode_baud_rate_divisor(buf, baud);

This works too if you don't want to pass in the port to
pl2303_encode_baud_rate_divisor() and hide the device-type differences
there (e.g. to make the logic in pl2303_encode_baud_rate() easier to
follow).

Johan



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

  Powered by Linux