Re: Likely issue with ch341 kernel-module/driver

From: Peter Stuge
Date: Thu Aug 27 2015 - 08:03:10 EST


Johan Hovold wrote:
> > I started in the morning to build the driver from the source provided
> > by the vendor, but it was written in the times of kernel-version 2.4,
> > and I got hopelessly stuck.
>
> The vendor driver is only for 2.4? Peter?

http://www.wch.cn/download/CH341SER_LINUX_ZIP.html
http://www.wch.cn/downfile/177

The vendor driver version 1.2 readme.txt from 2014-10-10 says:

Current Driver support versions of linux kernel range from 2.6.25 to 3.13.x

It didn't build immediately against the kernel I had at hand, but with
a small touchup (patch attached) it built fine against a 3.10 kernel.


> > Also, as per http://lxr.free-electrons.com/source/drivers/usb/serial/ch341.c?v=3.16,
> > the particular serial-USB-adapter device is added into the id_table,
> > so seems supported as per say.
>
> That id was added by 82078234d402 ("USB: serial: ch341: New VID/PID for
> CH341 USB-serial") in 2008, which claims that the driver supports both
> old and new devices.

My hardware has that same VID/PID, but there is a version request
sent to the device and my version number is quite a bit higher (20-30)
than what is mentioned in the in-tree driver comments; I guess the
protocol grew with newer versions of the device, but VID/PID weren't
updated. I'm sure it's possible to have a backwards-compatible
driver, but the vendor driver differs enough from the in-tree driver
that I can't be confident that simply doing what the vendor driver
does will work also on older versions of the device.


> > ###########################################################
> > usb 2-2: device not accepting address 8, error -71
> > ###########################################################
>
> This still looks like a hardware issue to me. Specifically, this happens
> before the ch341 driver is even involved.

I haven't seen any messages like this with my hardware.


//Peter
--- ch34x.c.orig 2014-04-14 10:38:44.000000000 +0200
+++ ch34x.c 2015-06-15 19:26:39.000000000 +0200
@@ -10,11 +10,7 @@
// Support linux kernel version 2.6.25 and later
//

-#include <linux/version.h>
-#ifndef KERNEL_VERSION
-#define KERNEL_VERSION(ver, rel, seq) ((ver << 16) | (rel << 8) | (seq))
-#endif
-
+#include <generated/uapi/linux/version.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
@@ -380,7 +376,7 @@
unsigned char reg_value = 0;
unsigned short value = 0;
unsigned short index = 0;
-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d", __func__, port->number);
#else
dbg_ch34x("%s - port:%d", __func__, port->port_number);
@@ -405,7 +401,7 @@
return;

cflag = termios->c_cflag;
-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s (%d) cflag=0x%x\n", __func__, port->number, cflag);
#else
dbg_ch34x("%s (%d) cflag=0x%x\n", __func__, port->port_number, cflag);
@@ -515,7 +511,7 @@
/*unsigned int msr;*/
unsigned int retval;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d", __func__, port->number);
#else
dbg_ch34x("%s - port:%d", __func__, port->port_number);
@@ -561,7 +557,7 @@
long timeout;
wait_queue_t wait;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d", __func__, port->number);
#else
dbg_ch34x("%s - port:%d", __func__, port->port_number);
@@ -636,7 +632,7 @@
struct usb_serial *serial = port->serial;
int retval;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d", __func__, port->number );
#else
dbg_ch34x("%s - port:%d", __func__, port->port_number );
@@ -710,7 +706,7 @@
/*unsigned int mcr = priv->line_control;*/
u8 control;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d", __func__, port->number);
#else
dbg_ch34x("%s - port:%d", __func__, port->port_number);
@@ -743,7 +739,7 @@
unsigned int status;
unsigned int changed;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s -port:%d", __func__, port->number);
#else
dbg_ch34x("%s -port:%d", __func__, port->port_number);
@@ -793,7 +789,7 @@
{
//struct usb_serial_port *port = tty->driver_data;
#endif
-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d, cmd=0x%04x", __func__, port->number, cmd);
#else
dbg_ch34x("%s - port:%d, cmd=0x%04x", __func__, port->port_number, cmd);
@@ -802,7 +798,7 @@
{
// Note here
case TIOCMIWAIT:
-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d TIOCMIWAIT", __func__, port->number);
#else
dbg_ch34x("%s - port:%d TIOCMIWAIT", __func__, port->port_number);
@@ -824,7 +820,7 @@
struct ch34x_private *priv = usb_get_serial_port_data( port );
unsigned long flags;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d", __func__, port->number);
#else
dbg_ch34x("%s - port:%d", __func__, port->port_number);
@@ -877,7 +873,7 @@
struct ch34x_private *priv = usb_get_serial_port_data(port);
unsigned long flags;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d, %d bytes", __func__, port->number, count);
#else
dbg_ch34x("%s - port:%d, %d bytes", __func__, port->port_number, count);
@@ -907,7 +903,7 @@
int room = 0;
unsigned long flags;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d", __func__, port->number);
#else
dbg_ch34x("%s - port:%d", __func__, port->port_number);
@@ -933,7 +929,7 @@
int chars = 0;
unsigned long flags;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d", __func__, port->number);
#else
dbg_ch34x("%s - port:%d", __func__, port->port_number);
@@ -1043,7 +1039,7 @@
int status = urb->status;
int retval;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s port:%d", __func__, port->number );
#else
dbg_ch34x("%s port:%d", __func__, port->port_number );
@@ -1091,7 +1087,7 @@
u8 line_status;
char tty_flag;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d", __func__, port->number );
#else
dbg_ch34x("%s - port:%d", __func__, port->port_number);
@@ -1197,7 +1193,7 @@
int retval;
int status = urb->status;

-#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
dbg_ch34x("%s - port:%d", __func__, port->number );
#else
dbg_ch34x("%s - port:%d", __func__, port->port_number );