Am 14.09.2013 12:13, schrieb Frank Schäfer:
> According to Prolific, several (unauthorized) cheap and less functional
> clones of the PL2303HX chip are in circulation. [1]
> I've had the chance to test such a cloned device and it turned out that
> it doesn't support any baud rates above 115200 baud (original: 6 Mbaud)
> It also doesn't support the divisior based baud rate encoding method,
> so no continuous baud rate adjustment is possible.
> Nevertheless, these devices have been working (unintentionally) with
> the driver up to commit 61fa8d694b ("pl2303: also use the divisor based
> baud rate encoding method for baud rates < 115200 with HX chips"), and
> this commit broke support for them.
> Fortunately, it is pretty simple to distinguish between the original
> and the cloned HX chips, so I've added a check and an extra chip type
> to keep the clones working.
> The same check is used by the latest Prolific Windows driver, so it
> should be solid.
>
> Signed-off-by: Frank Schäfer <[email protected]>
Changes since v1:
- always restore address 0x0606/0x8686 after the clone test
- update another code comment


Greg,

IMHO this patch must be regarded as a regression fix for 3.12.
Wether we should try to support cloned chips or not is of course
discussable.

Regards,
Frank

> ---
>  drivers/usb/serial/pl2303.c |   43 
> ++++++++++++++++++++++++++++++++-----------
>  1 Datei geändert, 32 Zeilen hinzugefügt(+), 11 Zeilen entfernt(-)
>
> diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
> index e7a84f0..bedf8e4 100644
> --- a/drivers/usb/serial/pl2303.c
> +++ b/drivers/usb/serial/pl2303.c
> @@ -139,6 +139,7 @@ enum pl2303_type {
>       HX_TA,          /* HX(A) / X(A) / TA version  */ /* TODO: improve */
>       HXD_EA_RA_SA,   /* HXD / EA / RA / SA version */ /* TODO: improve */
>       TB,             /* TB version */
> +     HX_CLONE,       /* Cheap and less functional clone of the HX chip */
>  };
>  /*
>   * NOTE: don't know the difference between type 0 and type 1,
> @@ -206,8 +207,23 @@ static int pl2303_startup(struct usb_serial *serial)
>                * the device descriptors of the X/HX, HXD, EA, RA, SA, TA, TB
>                */
>               if (le16_to_cpu(serial->dev->descriptor.bcdDevice) == 0x300) {
> -                     type = HX_TA;
> -                     type_str = "X/HX/TA";
> +                     /* Check if the device is a clone */
> +                     pl2303_vendor_read(0x9494, 0, serial, buf);
> +                     /*
> +                      * NOTE: Not sure if this read is really needed.
> +                      * The HX returns 0x00, the clone 0x02, but the Windows
> +                      * driver seems to ignore the value and continues.
> +                      */
> +                     pl2303_vendor_write(0x0606, 0xaa, serial);
> +                     pl2303_vendor_read(0x8686, 0, serial, buf);
> +                     if (buf[0] != 0xaa) {
> +                             type = HX_CLONE;
> +                             type_str = "X/HX clone (limited functionality)";
> +                     } else {
> +                             type = HX_TA;
> +                             type_str = "X/HX/TA";
> +                     }
> +                     pl2303_vendor_write(0x0606, 0x00, serial);
>               } else if (le16_to_cpu(serial->dev->descriptor.bcdDevice)
>                                                                    == 0x400) {
>                       type = HXD_EA_RA_SA;
> @@ -305,8 +321,9 @@ static int pl2303_baudrate_encode_direct(int baud, enum 
> pl2303_type type,
>  {
>       /*
>        * NOTE: Only the values defined in baud_sup are supported !
> -      *       => if unsupported values are set, the PL2303 seems to
> -      *          use 9600 baud (at least my PL2303X always does)
> +      * => if unsupported values are set, the PL2303 uses 9600 baud instead
> +      * => HX clones just don't work at unsupported baud rates < 115200 baud,
> +      *    for baud rates > 115200 they run at 115200 baud
>        */
>       const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600,
>                                4800, 7200, 9600, 14400, 19200, 28800, 38400,
> @@ -316,14 +333,14 @@ static int pl2303_baudrate_encode_direct(int baud, enum 
> pl2303_type type,
>        * NOTE: With the exception of type_0/1 devices, the following
>        * additional baud rates are supported (tested with HX rev. 3A only):
>        * 110*, 56000*, 128000, 134400, 161280, 201600, 256000*, 268800,
> -      * 403200, 806400.      (*: not HX)
> +      * 403200, 806400.      (*: not HX and HX clones)
>        *
>        * Maximum values: HXD, TB: 12000000; HX, TA: 6000000;
> -      *                 type_0+1: 1228800; RA: 921600; SA: 115200
> +      *                 type_0+1: 1228800; RA: 921600; HX clones, SA: 115200
>        *
>        * As long as we are not using this encoding method for anything else
> -      * than the type_0+1 and HX chips, there is no point in complicating
> -      * the code to support them.
> +      * than the type_0+1, HX and HX clone chips, there is no point in
> +      * complicating the code to support them.
>        */
>       int i;
>  
> @@ -347,6 +364,8 @@ static int pl2303_baudrate_encode_direct(int baud, enum 
> pl2303_type type,
>               baud = min_t(int, baud, 6000000);
>       else if (type == type_0 || type == type_1)
>               baud = min_t(int, baud, 1228800);
> +     else if (type == HX_CLONE)
> +             baud = min_t(int, baud, 115200);
>       /* Direct (standard) baud rate encoding method */
>       put_unaligned_le32(baud, buf);
>  
> @@ -359,7 +378,8 @@ static int pl2303_baudrate_encode_divisor(int baud, enum 
> pl2303_type type,
>       /*
>        * Divisor based baud rate encoding method
>        *
> -      * NOTE: it's not clear if the type_0/1 chips support this method
> +      * NOTE: HX clones do NOT support this method.
> +      * It's not clear if the type_0/1 chips support it.
>        *
>        * divisor = 12MHz * 32 / baudrate = 2^A * B
>        *
> @@ -452,7 +472,7 @@ static void pl2303_encode_baudrate(struct tty_struct *tty,
>        * 1) Direct method: encodes the baud rate value directly
>        *    => supported by all chip types
>        * 2) Divisor based method: encodes a divisor to a base value (12MHz*32)
> -      *    => supported by HX chips (and likely not by type_0/1 chips)
> +      *    => not supported by HX clones (and likely type_0/1 chips)
>        *
>        * NOTE: Although the divisor based baud rate encoding method is much
>        * more flexible, some of the standard baud rate values can not be
> @@ -460,7 +480,7 @@ static void pl2303_encode_baudrate(struct tty_struct *tty,
>        * the device likely uses the same baud rate generator for both methods
>        * so that there is likley no difference.
>        */
> -     if (type == type_0 || type == type_1)
> +     if (type == type_0 || type == type_1 || type == HX_CLONE)
>               baud = pl2303_baudrate_encode_direct(baud, type, buf);
>       else
>               baud = pl2303_baudrate_encode_divisor(baud, type, buf);
> @@ -813,6 +833,7 @@ static void pl2303_break_ctl(struct tty_struct *tty, int 
> break_state)
>       result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
>                                BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
>                                0, NULL, 0, 100);
> +     /* NOTE: HX clones don't support sending breaks, -EPIPE is returned */
>       if (result)
>               dev_err(&port->dev, "error sending break = %d\n", result);
>  }

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to