Re: [PATCH v2] pl2303: distinguish between original and cloned HX chips

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

 



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 <fschaefer.oss@xxxxxxxxxxxxxx>
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 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