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

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

 



On 3/5/21 4:36 AM, Johan Hovold wrote:
> On Fri, Mar 05, 2021 at 05:32:23PM +0800, Charles Yeh wrote:
>> 110 bps is not the standard Baud rate,
>> PL2303TA don't work with the current Linux driver (d5 0e 00 80), It
>> needs to "a8 a6 01 80"
> 
> Ok, thanks for confirming. Then we should be able to fix this up based
> on Michael's findings.
> 
>> Johan Hovold <johan@xxxxxxxxxx> 於 2021年2月25日 週四 上午1:00寫道:
>>
>>> But can you confirm that your PL2303TA works with the current Linux
>>> driver at 110 Bd (and doesn't need the alternate divisor encoding)?
> 
> Johan
> 

How about... altering the call to pl2303_encode_baud_rate_divisor (adding 'port')
       baud = pl2303_encode_baud_rate_divisor(port, buf, baud);

and checking for model and altering algorithm as below.

I've tested this on the TA version.

Michael



static speed_t pl2303_encode_baud_rate_divisor(struct usb_serial_port *port, unsigned char buf[4],
                                speed_t baud)
{
    unsigned int baseline, mantissa, exponent;
        unsigned int bcdDevice = port->serial->dev->descriptor.bcdDevice;
        unsigned int bcdUSB = port->serial->dev->descriptor.bcdUSB;

        enum model { eUNKNOWN, eHXD, eHXA, eTA } model;

   if ( bcdUSB == 0x0110 ) {
       if( bcdDevice == 0x0400 )
           model = eHXD;
       else if ( bcdDevice == 0x0300 )
           model = eHXA; // PL2303HX(A)/XA ( EOL : PHASED OUT SINCE 2012 )
       else
          model = eUNKNOWN;
    } else if( bcdUSB == 0x200 && bcdDevice == 0x0300 ) {
        model = eTA;
    }
    /*
     * Apparently the formula is:
     *   baudrate = 12M * 32 / (mantissa * 4^exponent)
     * where
     *   mantissa = buf[8:0]
     *   exponent = buf[11:9]
         *
         * TA version has more precision
         *      uses mantissa = buf[bits 10:0 ]
     *           exponent = buf[bits 15:13]
     *  and x2 prescaler enable by buf[bit 16]
     */
    baseline = 12000000 * 32;
    mantissa = baseline / baud;
    if (mantissa == 0)
        mantissa = 1;    /* Avoid dividing by zero if baud > 32*12M. */
    exponent = 0;

    if ( model == eTA ) {
        while (mantissa >= 2048) {
            // n.b. below is speculative for the TA chip and is based on original code
            if (exponent < 15) {   // we are going to divide this by 2 later
                mantissa >>= 1;    // divide by 2
                exponent++;        // currently log2 ... will become log4
            } else {
                /* Exponent is maxed. Trim mantissa and leave. */
                mantissa = 2047 ;
                break;
            }
        }
        buf[2] = exponent & 0x01;  // activate x2 prescaler if needed
        exponent >>= 1;            // now log base 4 (losing LSB)
        buf[1] = (exponent << 5) | (mantissa >> 8);
    } else {
        while (mantissa >= 512) {
            if (exponent < 7) {
                mantissa >>= 2; /* divide by 4 */
                exponent++;
            } else {
                /* Exponent is maxed. Trim mantissa and leave. */
                mantissa = 511;
                break;
           }
        }
        buf[2] = 0;
        buf[1] = exponent << 1 | mantissa >> 8;
    }

    buf[3] = 0x80;
    buf[0] = mantissa & 0xff;

    /* Calculate and return the exact baud rate. */
    baud = (baseline / mantissa / (buf[2] == 0x01 ? 2:1)) >> (exponent << 1);
    return baud;
}






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

  Powered by Linux