On Sun, Nov 16, 2025 at 05:24:37PM +0000, Mikolaj Kucharski wrote:
> 
> Hi.

Hi Mikolaj,

> I noticed today that multiple of my CH341 USB to serial adapters don't
> work as expected. They attach and are detected properly, but with `cu`
> or any other serial terminal emulator I cannot communicate with other
> end.
> 
> uchcom0 at uhub0 port 4 configuration 1 interface 0 "QinHeng Electronics 
> USB2.0-Ser!" rev 1.10/2.54 addr 2
> uchcom0: CH341
> ucom0 at uchcom0: usb0.0.00004.0
> 
> I get mainly underscore characters:
> 
> # cu -s 115200 -l /dev/cuaU0
> Connected to /dev/cuaU0 (speed 115200)
> _____l____fff"&_?_ynJ___I____)_____4________.__________________l_____
> 
> 
> However, when I revert uchcom.c -r1.39 back to -r1.38 my CH341 works
> correctly again.
> 
> Tested on:
> 
> OpenBSD 7.8-current (GENERIC.MP) #98: Sun Nov 16 08:46:59 MST 2025
>     [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> 
> but also on 7.7-stable and 7.8-stable.
> 
> 7.8-current -> broken
> 7.8-stable -> broken
> 7.7-stable -> works
> 7.8-current with uchcom.c -r1.38 -> works

First of all, thanks for debugging and identifying that version r1.39 caused 
your CH341 to stop working properly.

In r1.39, both the baud rate and the line configuration are set through 
UCHCOM_REQ_SET_BAUDRATE, whereas previously they were configured via 
UCHCOM_REG_BPS_PRE, UCHCOM_REG_BPS_DIV, UCHCOM_REG_LCR, and UCHCOM_REG_LCR2.

The diff below uses the old method to set the rate and line configuration.
My CH341 works fine with or without this diff, though.

Index: sys/dev/usb/uchcom.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uchcom.c,v
diff -u -p -u -p -r1.39 uchcom.c
--- sys/dev/usb/uchcom.c        19 Aug 2025 00:47:43 -0000      1.39
+++ sys/dev/usb/uchcom.c        17 Nov 2025 05:47:36 -0000
@@ -670,17 +670,27 @@ uchcom_set_dte_rate(struct uchcom_softc 
        uint8_t factor, div;
 
        uchcom_calc_baudrate(sc, rate, &div, &factor);
-       div |= (sc->sc_type != UCHCOM_TYPE_CH343) ? 0x80 : 0;
-       idx = (factor << 8) | div;
 
-       err = uchcom_generic_control_out(sc, UCHCOM_REQ_SET_BAUDRATE, val, idx);
-       if (err) {
-               printf("%s: cannot set DTE rate: %s\n",
-                   sc->sc_dev.dv_xname, usbd_errstr(err));
-               return EIO;
+       if (sc->sc_type != UCHCOM_TYPE_CH343) {
+               if ((err = uchcom_write_reg(sc,
+                   UCHCOM_REG_BPS_PRE, div | 0x80,
+                   UCHCOM_REG_BPS_DIV, factor)) ||
+                   (err = uchcom_write_reg(sc, UCHCOM_REG_LCR, val >> 8,
+                   UCHCOM_REG_LCR2, 0)))
+                       goto failed;
+       } else {
+               idx = (factor << 8) | div;
+               if ((err = uchcom_generic_control_out(sc,
+                   UCHCOM_REQ_SET_BAUDRATE, val, idx)))
+                       goto failed;
        }
 
        return 0;
+
+failed:
+       printf("%s: cannot set DTE rate: %s\n",
+           sc->sc_dev.dv_xname, usbd_errstr(err));
+       return EIO;
 }
 
 uint16_t

Reply via email to