Hello,

Recently I bought Arduino board which uses Nanjing QinHeng (WinChipHead)
CH340T USB-UART bridge via eBay, and I found uchcom(4) did not work.
At misc@, other user reported similar problem. [1]

The uchcom(4) comes from NetBSD and it seems to be worked at that time.

I found that uchcom_set_line_control() breaks the value of
UCHCOM_REG_LCR1(0x18) makes the problem. The UCHCOM_REG_LCR1 register
seems to control parity bit (none/odd/even) but I doubt the role of that
register has changed between old/new CH340T chip.

At least following changes are required to work my CH340T but parity bit
control is no longer supported.

If there is no problem, I want to commit.

[1] 
http://openbsd.7691.n7.nabble.com/issue-with-WinChipHead-CH340-usb-serial-td99678.html

Index: uchcom.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uchcom.c,v
retrieving revision 1.19
diff -u -p -r1.19 uchcom.c
--- uchcom.c    15 Nov 2013 10:17:39 -0000      1.19
+++ uchcom.c    13 May 2014 19:43:37 -0000
@@ -91,14 +91,6 @@ int  uchcomdebug = 0;
 #define UCHCOM_BRK1_MASK       0x01
 #define UCHCOM_BRK2_MASK       0x40
 
-#define UCHCOM_LCR1_MASK       0xAF
-#define UCHCOM_LCR2_MASK       0x07
-#define UCHCOM_LCR1_PARENB     0x80
-#define UCHCOM_LCR2_PAREVEN    0x07
-#define UCHCOM_LCR2_PARODD     0x06
-#define UCHCOM_LCR2_PARMARK    0x05
-#define UCHCOM_LCR2_PARSPACE   0x04
-
 #define UCHCOM_INTR_STAT1      0x02
 #define UCHCOM_INTR_STAT2      0x03
 #define UCHCOM_INTR_LEAST      4
@@ -707,27 +699,10 @@ uchcom_set_dte_rate(struct uchcom_softc 
 int
 uchcom_set_line_control(struct uchcom_softc *sc, tcflag_t cflag)
 {
-       usbd_status err;
-       uint8_t lcr1 = 0, lcr2 = 0;
-
-       err = uchcom_read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2,
-           &lcr2);
-       if (err) {
-               printf("%s: cannot get LCR: %s\n",
-                      sc->sc_dev.dv_xname, usbd_errstr(err));
-               return EIO;
-       }
-
-       lcr1 &= ~UCHCOM_LCR1_MASK;
-       lcr2 &= ~UCHCOM_LCR2_MASK;
-
        /*
         * XXX: it is difficult to handle the line control appropriately:
-        *   - CS8, !CSTOPB and any parity mode seems ok, but
-        *   - the chip doesn't have the function to calculate parity
-        *     in !CS8 mode.
-        *   - it is unclear that the chip supports CS5,6 mode.
-        *   - it is unclear how to handle stop bits.
+        *   work as chip default - CS8, no parity, !CSTOPB
+        *   other modes are not supported.
         */
 
        switch (ISSET(cflag, CSIZE)) {
@@ -739,21 +714,8 @@ uchcom_set_line_control(struct uchcom_so
                break;
        }
 
-       if (ISSET(cflag, PARENB)) {
-               lcr1 |= UCHCOM_LCR1_PARENB;
-               if (ISSET(cflag, PARODD))
-                       lcr2 |= UCHCOM_LCR2_PARODD;
-               else
-                       lcr2 |= UCHCOM_LCR2_PAREVEN;
-       }
-
-       err = uchcom_write_reg(sc, UCHCOM_REG_LCR1, lcr1, UCHCOM_REG_LCR2,
-           lcr2);
-       if (err) {
-               printf("%s: cannot set LCR: %s\n",
-                      sc->sc_dev.dv_xname, usbd_errstr(err));
-               return EIO;
-       }
+       if (ISSET(cflag, PARENB) || ISSET(cflag, CSTOPB))
+               return EINVAL;
 
        return 0;
 }
@@ -778,33 +740,10 @@ int
 uchcom_reset_chip(struct uchcom_softc *sc)
 {
        usbd_status err;
-       uint8_t lcr1, lcr2, pre, div, mod;
-       uint16_t val=0, idx=0;
-
-       err = uchcom_read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2, 
&lcr2);
-       if (err)
-               goto failed;
-
-       err = uchcom_read_reg(sc, UCHCOM_REG_BPS_PRE, &pre, UCHCOM_REG_BPS_DIV,
-           &div);
-       if (err)
-               goto failed;
-
-       err = uchcom_read_reg(sc, UCHCOM_REG_BPS_MOD, &mod, UCHCOM_REG_BPS_PAD,
-           NULL);
-       if (err)
-               goto failed;
+       uint16_t val, idx;
 
-       val |= (uint16_t)(lcr1&0xF0) << 8;
-       val |= 0x01;
-       val |= (uint16_t)(lcr2&0x0F) << 8;
-       val |= 0x02;
-       idx |= pre & 0x07;
-       val |= 0x04;
-       idx |= (uint16_t)div << 8;
-       val |= 0x08;
-       idx |= mod & 0xF8;
-       val |= 0x10;
+       val = 0x501f;
+       idx = 0xd90a;
 
        DPRINTF(("%s: reset v=0x%04X, i=0x%04X\n",
                 sc->sc_dev.dv_xname, val, idx));

Reply via email to