NetBSD-Bugs archive

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

kern/53913: 4World USB to Serial adapter fails on connection



>Number:         53913
>Category:       kern
>Synopsis:       4World USB to Serial adapter fails on connection
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jan 27 09:45:00 +0000 2019
>Originator:     Andrius V
>Release:        8.99.30
>Organization:
>Environment:
NetBSD vertexpc 8.99.30 NetBSD 8.99.30 (GENERIC) #0: Tue Jan 15 14:23:56 UTC 2019  mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/i386/compile/GENERIC i386
>Description:
I've recently bought 4World USB to Serial adapter which is based on WinChipHead CH341/340 chip.

from dmesg:
uchcom0: QinHeng Electronics (0x1a86) USB2.0-Ser! (0x7523), rev 1.10/2.54, addr 3
ucom0 at uchcom0
uchcom0: WARNING: power management not supported

Unfortunately, when I am trying to use with minicom (or any alternative app), I am receiving this error message:
uchcom0: cannot reset: STALLED

I investigated it minimally and it returns error on the second call in reset_chip method:
err = read_reg(sc, UCHCOM_REG_BPS_PRE, &pre, UCHCOM_REG_BPS_DIV, &div);

So, I checked OpenBSD driver and it seams they simplified reset code with some hardcoded values. I actually tried it and OpenBSD code works for me (with default configuration at least). minicom successfully started, communication between PCs was successful too. OpenBSD commit can be seen here https://github.com/openbsd/src/commit/5165e579a145cd62a9fbbbd8c33e30b50d88b5d1#diff-e15f5490917f699be5d06d933f46a0b2. 

However, I am not sure if it's desirable solution for NetBSD since I saw some recent development on the driver (issue is the same before or after those changes).
>How-To-Repeat:
Connect the cable to USB, try to start minicom with /dev/ttyU0 device. Check dmesg messages.
>Fix:
Workaround copied from OpenBSD:

Index: sys/dev/usb/uchcom.c
==================================================================
--- sys/dev/usb/uchcom.c
+++ sys/dev/usb/uchcom.c
@@ -116,10 +116,17 @@
 #define UCHCOM_INTR_LEAST	4
 
 #define UCHCOMIBUFSIZE 256
 #define UCHCOMOBUFSIZE 256
 
+/*
+ * XXX - these magic numbers come from Linux (drivers/usb/serial/ch341.c).
+ * The manufacturer was unresponsive when asked for documentation.
+ */
+#define UCHCOM_RESET_VALUE	0x501F	/* line mode? */
+#define UCHCOM_RESET_INDEX	0xD90A	/* baud rate? */
+
 struct uchcom_softc
 {
 	device_t		sc_dev;
 	struct usbd_device *	sc_udev;
 	device_t		sc_subdev;
@@ -761,31 +768,12 @@
 
 static int
 reset_chip(struct uchcom_softc *sc)
 {
 	usbd_status err;
-	uint8_t lcr, lcr2, pre, div;
-	uint16_t val=0, idx=0;
-
-	err = read_reg(sc, UCHCOM_REG_LCR, &lcr, UCHCOM_REG_LCR2, &lcr2);
-	if (err)
-		goto failed;
-
-	err = read_reg(sc, UCHCOM_REG_BPS_PRE, &pre, UCHCOM_REG_BPS_DIV, &div);
-	if (err)
-		goto failed;
-
-	val |= (uint16_t)lcr << 8;
-	val |= 0x9c;	/* magic from vendor Linux and Android drivers */
-	idx |= pre & 0x07;
-	idx |= (uint16_t)div << 8;
-	idx |= UCHCOM_BPS_PRE_IMM;
-
-	DPRINTF(("%s: reset v=0x%04X, i=0x%04X\n",
-		 device_xname(sc->sc_dev), val, idx));
-
-	err = generic_control_out(sc, UCHCOM_REQ_RESET, val, idx);
+	
+	err = generic_control_out(sc, UCHCOM_REQ_RESET, UCHCOM_RESET_VALUE, UCHCOM_RESET_INDEX);
 	if (err)
 		goto failed;
 
 	return 0;



Home | Main Index | Thread Index | Old Index