Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Jun 2025 05:53:08 +0000
From:      Colin Percival <cperciva@tarsnap.com>
To:        Ronald Klop <ronald-lists@klop.ws>, Kevin Lo <kevlo@FreeBSD.org>
Cc:        dev-commits-src-all@FreeBSD.org, src-committers@FreeBSD.org,  dev-commits-src-main@FreeBSD.org
Subject:   Re: git: 1395712cab8e - main - uchcom: add support for CH9102 and CH343 uarts
Message-ID:  <01000197a5a5aff1-ed598ba1-80f2-406b-b11d-fc36e727d9c7-000000@email.amazonses.com>
In-Reply-To: <727722724.560.1750830351345@localhost>
References:  <202506250136.55P1aag8094334@gitrepo.freebsd.org> <727722724.560.1750830351345@localhost>

next in thread | previous in thread | raw e-mail | index | archive | help
Yes.  Please keep the HARDWARE section in device driver man pages.  The
text from there goes directly into the "hardware notes" page on the website.

Colin Percival

On 6/24/25 22:45, Ronald Klop wrote:
> Hi,
> 
> nice work!
> 
> Isn't the HARDWARE section in the man page used to generate a supported 
> hardware list in the release notes of a new FreeBSD version?
> 
> Regards,
> Ronald.
> 
> *Van:* Kevin Lo <kevlo@FreeBSD.org>
> *Datum:*woensdag, 25 juni 2025 03:36
> *Aan:*src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev- 
> commits-src-main@FreeBSD.org
> *Onderwerp:*git: 1395712cab8e - main - uchcom: add support for CH9102 and 
> CH343 uarts
> 
>     The branch main has been updated by kevlo:
> 
>     URL: https://cgit.FreeBSD.org/src/commit/?
>     id=1395712cab8e95808064ba68c5a792b7cd0fe35f <https://cgit.FreeBSD.org/src/
>     commit/?id=1395712cab8e95808064ba68c5a792b7cd0fe35f>
> 
>     commit 1395712cab8e95808064ba68c5a792b7cd0fe35f
>     Author:     Kevin Lo <kevlo@FreeBSD.org>
>     AuthorDate: 2025-06-25 01:33:35 +0000
>     Commit:     Kevin Lo <kevlo@FreeBSD.org>
>     CommitDate: 2025-06-25 01:33:35 +0000
> 
>          uchcom: add support for CH9102 and CH343 uarts
> 
>          The CH343 devices support any baud rate up to 6 Mbps.
>          PR:     272803
>          Reviewed by:    imp
>          Tested by:      joerg, Tomasz "CeDeROM" CEDRO <tomek_AT_cedro_DOT_info>
>          Differential Revision: https://reviews.freebsd.org/D46290 <https://
>     reviews.freebsd.org/D46290>
>     ---
>       share/man/man4/uchcom.4     |  27 +---
>       sys/dev/usb/serial/uchcom.c | 353 ++++++++++++++++++++++++
>     +-------------------
>       sys/dev/usb/usbdevs         |   4 +-
>       3 files changed, 208 insertions(+), 176 deletions(-)
> 
>     diff --git a/share/man/man4/uchcom.4 b/share/man/man4/uchcom.4
>     index d5efe83286ba..4d395573589f 100644
>     --- a/share/man/man4/uchcom.4
>     +++ b/share/man/man4/uchcom.4
>     @@ -27,12 +27,12 @@
>       .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
>     OF THE
>       .\" POSSIBILITY OF SUCH DAMAGE.
>       .\"
>     -.Dd April 26, 2017
>     +.Dd August 19, 2024
>       .Dt UCHCOM 4
>       .Os
>       .Sh NAME
>       .Nm uchcom
>     -.Nd WinChipHead CH341/CH340 serial adapter driver
>     +.Nd WinChipHead CH9102/CH343/CH341/CH340 serial adapter driver
>       .Sh SYNOPSIS
>       To compile this driver into the kernel,
>       place the following lines in your
>     @@ -52,22 +52,12 @@ uchcom_load="YES"
>       .Sh DESCRIPTION
>       The
>       .Nm
>     -driver provides support for the WinChipHead CH341/CH340 USB-to-RS-232
>     -Bridge chip.
>     +driver provides support for the WinChipHead CH9102/CH343/CH341/CH340
>     +USB-to-RS-232 Bridge chip.
>       .Pp
>     -The device is accessed through the
>     -.Xr ucom 4
>     -driver which makes it behave like a
>     -.Xr tty 4 .
>     -.Sh HARDWARE
>     -The
>     -.Nm
>     -driver supports the following adapters:
>     -.Pp
>     -.Bl -bullet -compact
>     -.It
>     -HL USB-RS232
>     -.El
>     +The datasheets for the CH340/CH341 list the maximum
>     +supported baud rate as 2,000,000.
>     +CH9102/CH343 devices support any baud rate up to 6 Mbps.
>       .Sh FILES
>       .Bl -tag -width "/dev/ttyU*.init" -compact
>       .It Pa /dev/ttyU*
>     @@ -95,6 +85,3 @@ The first
>       .Fx
>       release to include it was
>       .Fx 8.0 .
>     -.Sh BUGS
>     -Actually, this chip seems unable to drive other than 8 data bits and
>     -1 stop bit line.
>     diff --git a/sys/dev/usb/serial/uchcom.c b/sys/dev/usb/serial/uchcom.c
>     index a886b25c89d7..fdc5515fa722 100644
>     --- a/sys/dev/usb/serial/uchcom.c
>     +++ b/sys/dev/usb/serial/uchcom.c
>     @@ -58,8 +58,7 @@
>        */
> 
>       /*
>     - * Driver for WinChipHead CH341/340, the worst USB-serial chip in the
>     - * world.
>     + * Driver for WinChipHead CH9102/343/341/340.
>        */
> 
>       #include <sys/stdint.h>
>     @@ -101,17 +100,19 @@ SYSCTL_INT(_hw_usb_uchcom, OID_AUTO, debug,
>     CTLFLAG_RWTUN,
>           &uchcom_debug, 0, "uchcom debug level");
>       #endif
> 
>     -#define    UCHCOM_IFACE_INDEX  0
>     -#define    UCHCOM_CONFIG_INDEX 0
>     +#define    UCHCOM_IFACE_INDEX      0
>     +#define    UCHCOM_CONFIG_INDEX     0
>     +#define    UCHCOM_SECOND_IFACE_INDEX   1
> 
>       #define    UCHCOM_REV_CH340    0x0250
>       #define    UCHCOM_INPUT_BUF_SIZE   8
> 
>     -#define    UCHCOM_REQ_GET_VERSION  0x5F
>     -#define    UCHCOM_REQ_READ_REG 0x95
>     -#define    UCHCOM_REQ_WRITE_REG    0x9A
>     -#define    UCHCOM_REQ_RESET    0xA1
>     -#define    UCHCOM_REQ_SET_DTRRTS   0xA4
>     +#define    UCHCOM_REQ_GET_VERSION      0x5F
>     +#define    UCHCOM_REQ_READ_REG     0x95
>     +#define    UCHCOM_REQ_WRITE_REG        0x9A
>     +#define    UCHCOM_REQ_RESET        0xA1
>     +#define    UCHCOM_REQ_SET_DTRRTS       0xA4
>     +#define UCHCOM_REQ_CH343_WRITE_REG 0xA8
> 
>       #define    UCHCOM_REG_STAT1    0x06
>       #define    UCHCOM_REG_STAT2    0x07
>     @@ -134,13 +135,21 @@ SYSCTL_INT(_hw_usb_uchcom, OID_AUTO, debug,
>     CTLFLAG_RWTUN,
>       #define    UCHCOM_RTS_MASK     0x40
> 
>       #define    UCHCOM_BRK_MASK     0x01
>     +#define    UCHCOM_ABRK_MASK    0x10
>     +#define    UCHCOM_CH343_BRK_MASK   0x80
> 
>       #define    UCHCOM_LCR1_MASK    0xAF
>       #define    UCHCOM_LCR2_MASK    0x07
>       #define    UCHCOM_LCR1_RX      0x80
>       #define    UCHCOM_LCR1_TX      0x40
>       #define    UCHCOM_LCR1_PARENB  0x08
>     +#define    UCHCOM_LCR1_CS5     0x00
>     +#define    UCHCOM_LCR1_CS6     0x01
>     +#define    UCHCOM_LCR1_CS7     0x02
>       #define    UCHCOM_LCR1_CS8     0x03
>     +#define    UCHCOM_LCR1_STOPB   0x04
>     +#define    UCHCOM_LCR1_PARODD  0x00
>     +#define    UCHCOM_LCR1_PAREVEN 0x10
>       #define    UCHCOM_LCR2_PAREVEN 0x07
>       #define    UCHCOM_LCR2_PARODD  0x06
>       #define    UCHCOM_LCR2_PARMARK 0x05
>     @@ -150,12 +159,18 @@ SYSCTL_INT(_hw_usb_uchcom, OID_AUTO, debug,
>     CTLFLAG_RWTUN,
>       #define    UCHCOM_INTR_STAT2   0x03
>       #define    UCHCOM_INTR_LEAST   4
> 
>     -#define    UCHCOM_BULK_BUF_SIZE 1024   /* bytes */
>     +#define    UCHCOM_T        0x08
>     +#define    UCHCOM_CL       0x04
>     +#define    UCHCOM_CH343_CT     0x80
>     +#define    UCHCOM_CT       0x90
>     +
>     +#define    UCHCOM_BULK_BUF_SIZE    1024    /* bytes */
>     +
>     +#define    TYPE_CH343      1
> 
>       enum {
>          UCHCOM_BULK_DT_WR,
>          UCHCOM_BULK_DT_RD,
>     -   UCHCOM_INTR_DT_RD,
>          UCHCOM_N_TRANSFER,
>       };
> 
>     @@ -164,6 +179,7 @@ struct uchcom_softc {
>          struct ucom_softc sc_ucom;
> 
>          struct usb_xfer *sc_xfer[UCHCOM_N_TRANSFER];
>     +   struct usb_xfer *sc_intr_xfer;  /* Interrupt endpoint */
>          struct usb_device *sc_udev;
>          struct mtx sc_mtx;
> 
>     @@ -171,39 +187,19 @@ struct uchcom_softc {
>          uint8_t sc_rts;         /* local copy */
>          uint8_t sc_version;
>          uint8_t sc_msr;
>     -   uint8_t sc_lsr;         /* local status register */
>     -};
>     -
>     -struct uchcom_divider {
>     -   uint8_t dv_prescaler;
>     -   uint8_t dv_div;
>     -   uint8_t dv_mod;
>     -};
>     -
>     -struct uchcom_divider_record {
>     -   uint32_t dvr_high;
>     -   uint32_t dvr_low;
>     -   uint32_t dvr_base_clock;
>     -   struct uchcom_divider dvr_divider;
>     -};
>     -
>     -static const struct uchcom_divider_record dividers[] =
>     -{
>     -   {307200, 307200, UCHCOM_BASE_UNKNOWN, {7, 0xD9, 0}},
>     -   {921600, 921600, UCHCOM_BASE_UNKNOWN, {7, 0xF3, 0}},
>     -   {2999999, 23530, 6000000, {3, 0, 0}},
>     -   {23529, 2942, 750000, {2, 0, 0}},
>     -   {2941, 368, 93750, {1, 0, 0}},
>     -   {367, 1, 11719, {0, 0, 0}},
>     +   uint8_t sc_lsr;         /* local status register */
>     +   uint8_t sc_chiptype;        /* type of chip */
>     +   uint8_t sc_ctrl_iface_no;
>     +   uint8_t sc_iface_index;
>       };
> 
>     -#define    NUM_DIVIDERS    nitems(dividers)
>     -
>       static const STRUCT_USB_HOST_ID uchcom_devs[] = {
>          {USB_VPI(USB_VENDOR_WCH, USB_PRODUCT_WCH_CH341SER, 0)},
>          {USB_VPI(USB_VENDOR_WCH2, USB_PRODUCT_WCH2_CH341SER, 0)},
>          {USB_VPI(USB_VENDOR_WCH2, USB_PRODUCT_WCH2_CH341SER_2, 0)},
>          {USB_VPI(USB_VENDOR_WCH2, USB_PRODUCT_WCH2_CH341SER_3, 0)},
>     +   {USB_VPI(USB_VENDOR_WCH2, USB_PRODUCT_WCH2_CH343SER, 0)},
>     +   {USB_VPI(USB_VENDOR_WCH2, USB_PRODUCT_WCH2_CH9102SER, 0)},
>       };
> 
>       /* protypes */
>     @@ -225,8 +221,9 @@ static void uchcom_update_version(struct uchcom_softc *);
>       static void    uchcom_convert_status(struct uchcom_softc *, uint8_t);
>       static void    uchcom_update_status(struct uchcom_softc *);
>       static void    uchcom_set_dtr_rts(struct uchcom_softc *);
>     -static int uchcom_calc_divider_settings(struct uchcom_divider *, uint32_t);
>     -static void    uchcom_set_baudrate(struct uchcom_softc *, uint32_t);
>     +static void    uchcom_calc_baudrate(struct uchcom_softc *, uint32_t,
>     uint8_t *,
>     +           uint8_t *);
>     +static void    uchcom_set_baudrate(struct uchcom_softc *, uint32_t,
>     uint16_t);
>       static void    uchcom_poll(struct ucom_softc *ucom);
> 
>       static device_probe_t uchcom_probe;
>     @@ -244,7 +241,7 @@ static const struct usb_config
>     uchcom_config_data[UCHCOM_N_TRANSFER] = {
>              .endpoint = UE_ADDR_ANY,
>              .direction = UE_DIR_OUT,
>              .bufsize = UCHCOM_BULK_BUF_SIZE,
>     -       .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
>     +       .flags = {.pipe_bof = 1,},
>              .callback = &uchcom_write_callback,
>          },
> 
>     @@ -256,8 +253,10 @@ static const struct usb_config
>     uchcom_config_data[UCHCOM_N_TRANSFER] = {
>              .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
>              .callback = &uchcom_read_callback,
>          },
>     +};
> 
>     -   [UCHCOM_INTR_DT_RD] = {
>     +static const struct usb_config uchcom_intr_config_data[1] = {
>     +   [0] = {
>              .type = UE_INTERRUPT,
>              .endpoint = UE_ADDR_ANY,
>              .direction = UE_DIR_IN,
>     @@ -311,8 +310,9 @@ uchcom_attach(device_t dev)
>       {
>          struct uchcom_softc *sc = device_get_softc(dev);
>          struct usb_attach_arg *uaa = device_get_ivars(dev);
>     +   struct usb_interface *iface;
>     +   struct usb_interface_descriptor *id;
>          int error;
>     -   uint8_t iface_index;
> 
>          DPRINTFN(11, "\n");
> 
>     @@ -330,20 +330,49 @@ uchcom_attach(device_t dev)
>          case USB_PRODUCT_WCH2_CH341SER_3:
>              device_printf(dev, "CH341 detected\n");
>              break;
>     +   case USB_PRODUCT_WCH2_CH343SER:
>     +       device_printf(dev, "CH343 detected\n");
>     +       break;
>     +   case USB_PRODUCT_WCH2_CH9102SER:
>     +       device_printf(dev, "CH9102 detected\n");
>     +       break;
>          default:
>     -       device_printf(dev, "New CH340/CH341 product 0x%04x detected\n",
>     -           uaa->info.idProduct);
>     +       device_printf(dev, "New CH340/CH341/CH343/CH9102 product "
>     +           "0x%04x detected\n", uaa->info.idProduct);
>              break;
>          }
> 
>     -   iface_index = UCHCOM_IFACE_INDEX;
>     -   error = usbd_transfer_setup(uaa->device,
>     -       &iface_index, sc->sc_xfer, uchcom_config_data,
>     -       UCHCOM_N_TRANSFER, sc, &sc->sc_mtx);
>     +   /* CH343/CH9102 has two interfaces. */
>     +   sc->sc_ctrl_iface_no = uaa->info.bIfaceNum;
> 
>     +   iface = usbd_get_iface(uaa->device, UCHCOM_SECOND_IFACE_INDEX);
>     +   if (iface) {
>     +       id = usbd_get_interface_descriptor(iface);
>     +       if (id == NULL) {
>     +           device_printf(dev, "no interface descriptor\n");
>     +           goto detach;
>     +       }
>     +       sc->sc_iface_index = UCHCOM_SECOND_IFACE_INDEX;
>     +       usbd_set_parent_iface(uaa->device, UCHCOM_SECOND_IFACE_INDEX,
>     +           uaa->info.bIfaceIndex);
>     +       sc->sc_chiptype = TYPE_CH343;
>     +   } else {
>     +       sc->sc_iface_index = UCHCOM_IFACE_INDEX;
>     +   }
>     +
>     +   /* Setup all transfers. */
>     +   error = usbd_transfer_setup(uaa->device, &sc->sc_iface_index,
>     +       sc->sc_xfer, uchcom_config_data, UCHCOM_N_TRANSFER, sc,
>     +       &sc->sc_mtx);
>     +   if (error) {
>     +       device_printf(dev, "could not allocate all pipes\n");
>     +       goto detach;
>     +   }
>     +   error = usbd_transfer_setup(uaa->device, &sc->sc_ctrl_iface_no,
>     +       &sc->sc_intr_xfer, uchcom_intr_config_data, 1, sc, &sc->sc_mtx);
>          if (error) {
>     -       DPRINTF("one or more missing USB endpoints, "
>     -           "error=%s\n", usbd_errstr(error));
>     +       device_printf(dev, "allocating USB transfers failed for "
>     +           "interrupt\n");
>              goto detach;
>          }
> 
>     @@ -449,7 +478,9 @@ uchcom_write_reg(struct uchcom_softc *sc,
>              (unsigned)reg1, (unsigned)val1,
>              (unsigned)reg2, (unsigned)val2);
>          uchcom_ctrl_write(
>     -       sc, UCHCOM_REQ_WRITE_REG,
>     +       sc,
>     +       (sc->sc_chiptype != TYPE_CH343) ?
>     +       UCHCOM_REQ_WRITE_REG : UCHCOM_REQ_CH343_WRITE_REG,
>              reg1 | ((uint16_t)reg2 << 8), val1 | ((uint16_t)val2 << 8));
>       }
> 
>     @@ -516,9 +547,6 @@ uchcom_update_version(struct uchcom_softc *sc)
>       static void
>       uchcom_convert_status(struct uchcom_softc *sc, uint8_t cur)
>       {
>     -   sc->sc_dtr = !(cur & UCHCOM_DTR_MASK);
>     -   sc->sc_rts = !(cur & UCHCOM_RTS_MASK);
>     -
>          cur = ~cur & 0x0F;
>          sc->sc_msr = (cur << 4) | ((sc->sc_msr >> 4) ^ cur);
>       }
>     @@ -555,78 +583,69 @@ uchcom_cfg_set_break(struct ucom_softc *ucom,
>     uint8_t onoff)
>          uint8_t brk1;
>          uint8_t brk2;
> 
>     -   uchcom_read_reg(sc, UCHCOM_REG_BREAK1, &brk1, UCHCOM_REG_LCR1, &brk2);
>     -   if (onoff) {
>     -       /* on - clear bits */
>     -       brk1 &= ~UCHCOM_BRK_MASK;
>     -       brk2 &= ~UCHCOM_LCR1_TX;
>     +   if (sc->sc_chiptype == TYPE_CH343) {
>     +       brk1 = UCHCOM_CH343_BRK_MASK;
>     +       if (!onoff)
>     +           brk1 |= UCHCOM_ABRK_MASK;
>     +       uchcom_write_reg(sc, brk1, 0, 0, 0);
>          } else {
>     -       /* off - set bits */
>     -       brk1 |= UCHCOM_BRK_MASK;
>     -       brk2 |= UCHCOM_LCR1_TX;
>     +       uchcom_read_reg(sc, UCHCOM_REG_BREAK1, &brk1, UCHCOM_REG_LCR1,
>     +           &brk2);
>     +       if (onoff) {
>     +           /* on - clear bits */
>     +           brk1 &= ~UCHCOM_BRK_MASK;
>     +           brk2 &= ~UCHCOM_LCR1_TX;
>     +       } else {
>     +           /* off - set bits */
>     +           brk1 |= UCHCOM_BRK_MASK;
>     +           brk2 |= UCHCOM_LCR1_TX;
>     +       }
>     +       uchcom_write_reg(sc, UCHCOM_REG_BREAK1, brk1, UCHCOM_REG_LCR1,
>     +           brk2);
>          }
>     -   uchcom_write_reg(sc, UCHCOM_REG_BREAK1, brk1, UCHCOM_REG_LCR1, brk2);
>       }
> 
>     -static int
>     -uchcom_calc_divider_settings(struct uchcom_divider *dp, uint32_t rate)
>     -{
>     -   const struct uchcom_divider_record *rp;
>     -   uint32_t div;
>     -   uint32_t rem;
>     -   uint32_t mod;
>     -   uint8_t i;
>     -
>     -   /* find record */
>     -   for (i = 0; i != NUM_DIVIDERS; i++) {
>     -       if (dividers[i].dvr_high >= rate &&
>     -           dividers[i].dvr_low <= rate) {
>     -           rp = &dividers[i];
>     -           goto found;
>     -       }
>     -   }
>     -   return (-1);
>     -
>     -found:
>     -   dp->dv_prescaler = rp->dvr_divider.dv_prescaler;
>     -   if (rp->dvr_base_clock == UCHCOM_BASE_UNKNOWN)
>     -       dp->dv_div = rp->dvr_divider.dv_div;
>     -   else {
>     -       div = rp->dvr_base_clock / rate;
>     -       rem = rp->dvr_base_clock % rate;
>     -       if (div == 0 || div >= 0xFF)
>     -           return (-1);
>     -       if ((rem << 1) >= rate)
>     -           div += 1;
>     -       dp->dv_div = (uint8_t)-div;
>     +static void
>     +uchcom_calc_baudrate(struct uchcom_softc *sc, uint32_t rate, uint8_t
>     *divisor,
>     +    uint8_t *factor)
>     +{
>     +   uint32_t clk = 12000000;
>     +
>     +   if (rate >= 256000 && sc->sc_chiptype == TYPE_CH343)
>     +       *divisor = 7;
>     +   else if (rate > 23529) {
>     +       clk /= 2;
>     +       *divisor = 3;
>     +   } else if (rate > 2941) {
>     +       clk /=  16;
>     +       *divisor = 2;
>     +   } else if (rate > 367) {
>     +       clk /= 128;
>     +       *divisor = 1;
>     +   } else {
>     +       clk = 11719;
>     +       *divisor = 0;
>          }
> 
>     -   mod = (UCHCOM_BPS_MOD_BASE / rate) + UCHCOM_BPS_MOD_BASE_OFS;
>     -   mod = mod + (mod / 2);
>     +   *factor = 256 - clk / rate;
> 
>     -   dp->dv_mod = (mod + 0xFF) / 0x100;
>     -
>     -   return (0);
>     +   if (rate == 921600 && sc->sc_chiptype != TYPE_CH343) {
>     +       *divisor = 7;
>     +       *factor = 243;
>     +   }
>       }
> 
>       static void
>     -uchcom_set_baudrate(struct uchcom_softc *sc, uint32_t rate)
>     +uchcom_set_baudrate(struct uchcom_softc *sc, uint32_t rate, uint16_t lcr)
>       {
>     -   struct uchcom_divider dv;
>     +   uint16_t idx;
>     +   uint8_t factor, div;
> 
>     -   if (uchcom_calc_divider_settings(&dv, rate))
>     -       return;
>     +   uchcom_calc_baudrate(sc, rate, &div, &factor);
>     +   div |= (sc->sc_chiptype != TYPE_CH343) ? 0x80 : 0x00;
>     +   idx = (factor << 8) | div;
> 
>     -   /*
>     -    * According to linux code we need to set bit 7 of UCHCOM_REG_BPS_PRE,
>     -    * otherwise the chip will buffer data.
>     -    */
>     -   uchcom_write_reg(sc,
>     -       UCHCOM_REG_BPS_PRE, dv.dv_prescaler | 0x80,
>     -       UCHCOM_REG_BPS_DIV, dv.dv_div);
>     -   uchcom_write_reg(sc,
>     -       UCHCOM_REG_BPS_MOD, dv.dv_mod,
>     -       UCHCOM_REG_BPS_PAD, 0);
>     +   uchcom_ctrl_write(sc, UCHCOM_REQ_RESET, lcr, idx);
>       }
> 
>       /* ----------------------------------------------------------------------
>     @@ -673,6 +692,14 @@ uchcom_cfg_open(struct ucom_softc *ucom)
> 
>          DPRINTF("\n");
> 
>     +   if (sc->sc_chiptype != TYPE_CH343) {
>     +       /* Set default configuration. */
>     +       uchcom_get_version(sc, NULL);
>     +       uchcom_ctrl_write(sc, UCHCOM_REQ_RESET, 0, 0);
>     +       uchcom_write_reg(sc, UCHCOM_REG_BPS_PRE, 0x82,
>     +           UCHCOM_REG_BPS_DIV, 0xd9);
>     +       uchcom_write_reg(sc, 0x2c, 0x07, UCHCOM_REG_BPS_PAD, 0);
>     +   }
>          uchcom_update_version(sc);
>          uchcom_update_status(sc);
>       }
>     @@ -680,53 +707,69 @@ uchcom_cfg_open(struct ucom_softc *ucom)
>       static int
>       uchcom_pre_param(struct ucom_softc *ucom, struct termios *t)
>       {
>     -   struct uchcom_divider dv;
>     +   struct uchcom_softc *sc = ucom->sc_parent;
> 
>     -   switch (t->c_cflag & CSIZE) {
>     -   case CS8:
>     +   /*
>     +    * Check requested baud rate.
>     +    * The CH340/CH341 can set any baud rate up to 2Mb.
>     +    * The CH9102/CH343 can set any baud rate up to 6Mb.
>     +    */
>     +   switch (sc->sc_chiptype) {
>     +   case TYPE_CH343:
>     +       if (t->c_ospeed <= 6000000)
>     +           return (0);
>              break;
>          default:
>     -       return (EIO);
>     +       if (t->c_ospeed <= 2000000)
>     +           return (0);
>     +       break;
>          }
>     -   if ((t->c_cflag & CSTOPB) != 0)
>     -       return (EIO);
>     -   if ((t->c_cflag & PARENB) != 0)
>     -       return (EIO);
> 
>     -   if (uchcom_calc_divider_settings(&dv, t->c_ospeed)) {
>     -       return (EIO);
>     -   }
>     -   return (0);         /* success */
>     +   return (EIO);
>       }
> 
>       static void
>       uchcom_cfg_param(struct ucom_softc *ucom, struct termios *t)
>       {
>          struct uchcom_softc *sc = ucom->sc_parent;
>     +   uint8_t lcr;
> 
>     -   uchcom_get_version(sc, NULL);
>     -   uchcom_ctrl_write(sc, UCHCOM_REQ_RESET, 0, 0);
>     -   uchcom_set_baudrate(sc, t->c_ospeed);
>     -   if (sc->sc_version < UCHCOM_VER_30) {
>     -       uchcom_read_reg(sc, UCHCOM_REG_LCR1, NULL,
>     -           UCHCOM_REG_LCR2, NULL);
>     -       uchcom_write_reg(sc, UCHCOM_REG_LCR1, 0x50,
>     -           UCHCOM_REG_LCR2, 0x00);
>     -   } else {
>     -       /*
>     -        * Set up line control:
>     -        * - enable transmit and receive
>     -        * - set 8n1 mode
>     -        * To do: support other sizes, parity, stop bits.
>     -        */
>     -       uchcom_write_reg(sc,
>     -           UCHCOM_REG_LCR1,
>     -           UCHCOM_LCR1_RX | UCHCOM_LCR1_TX | UCHCOM_LCR1_CS8,
>     -           UCHCOM_REG_LCR2, 0x00);
>     +   lcr = UCHCOM_LCR1_RX | UCHCOM_LCR1_TX;
>     +
>     +   if (t->c_cflag & CSTOPB)
>     +       lcr |= UCHCOM_LCR1_STOPB;
>     +
>     +   if (t->c_cflag & PARENB) {
>     +       lcr |= UCHCOM_LCR1_PARENB;
>     +       if (t->c_cflag & PARODD)
>     +           lcr |= UCHCOM_LCR1_PARODD;
>     +       else
>     +           lcr |= UCHCOM_LCR1_PAREVEN;
>          }
>     -   uchcom_update_status(sc);
>     -   uchcom_ctrl_write(sc, UCHCOM_REQ_RESET, 0x501f, 0xd90a);
>     -   uchcom_set_baudrate(sc, t->c_ospeed);
>     +
>     +   switch (t->c_cflag & CSIZE) {
>     +   case CS5:
>     +       lcr |= UCHCOM_LCR1_CS5;
>     +       break;
>     +   case CS6:
>     +       lcr |= UCHCOM_LCR1_CS6;
>     +       break;
>     +   case CS7:
>     +       lcr |= UCHCOM_LCR1_CS7;
>     +       break;
>     +   case CS8:
>     +   default:
>     +       lcr |= UCHCOM_LCR1_CS8;
>     +       break;
>     +   }
>     +
>     +   if (sc->sc_chiptype == TYPE_CH343)
>     +       uchcom_set_baudrate(sc, t->c_ospeed,
>     +           UCHCOM_T | UCHCOM_CL | UCHCOM_CH343_CT | lcr << 8);
>     +   else
>     +       uchcom_set_baudrate(sc, t->c_ospeed,
>     +           UCHCOM_T | UCHCOM_CL | UCHCOM_CT | lcr << 8);
>     +
>          uchcom_set_dtr_rts(sc);
>          uchcom_update_status(sc);
>       }
>     @@ -737,7 +780,7 @@ uchcom_start_read(struct ucom_softc *ucom)
>          struct uchcom_softc *sc = ucom->sc_parent;
> 
>          /* start interrupt endpoint */
>     -   usbd_transfer_start(sc->sc_xfer[UCHCOM_INTR_DT_RD]);
>     +   usbd_transfer_start(sc->sc_intr_xfer);
> 
>          /* start read endpoint */
>          usbd_transfer_start(sc->sc_xfer[UCHCOM_BULK_DT_RD]);
>     @@ -749,7 +792,7 @@ uchcom_stop_read(struct ucom_softc *ucom)
>          struct uchcom_softc *sc = ucom->sc_parent;
> 
>          /* stop interrupt endpoint */
>     -   usbd_transfer_stop(sc->sc_xfer[UCHCOM_INTR_DT_RD]);
>     +   usbd_transfer_stop(sc->sc_intr_xfer);
> 
>          /* stop read endpoint */
>          usbd_transfer_stop(sc->sc_xfer[UCHCOM_BULK_DT_RD]);
>     @@ -779,7 +822,8 @@ uchcom_intr_callback(struct usb_xfer *xfer,
>     usb_error_t error)
>       {
>          struct uchcom_softc *sc = usbd_xfer_softc(xfer);
>          struct usb_page_cache *pc;
>     -   uint8_t buf[UCHCOM_INTR_LEAST];
>     +   uint32_t intrstat;
>     +   uint8_t buf[16];
>          int actlen;
> 
>          usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
>     @@ -791,13 +835,12 @@ uchcom_intr_callback(struct usb_xfer *xfer,
>     usb_error_t error)
> 
>              if (actlen >= UCHCOM_INTR_LEAST) {
>                  pc = usbd_xfer_get_frame(xfer, 0);
>     -           usbd_copy_out(pc, 0, buf, UCHCOM_INTR_LEAST);
>     +           usbd_copy_out(pc, 0, buf, sizeof(buf));
> 
>     -           DPRINTF("data = 0x%02X 0x%02X 0x%02X 0x%02X\n",
>     -               (unsigned)buf[0], (unsigned)buf[1],
>     -               (unsigned)buf[2], (unsigned)buf[3]);
>     +           intrstat = (sc->sc_chiptype == TYPE_CH343) ?
>     +               actlen - 1 : UCHCOM_INTR_STAT1;
> 
>     -           uchcom_convert_status(sc, buf[UCHCOM_INTR_STAT1]);
>     +           uchcom_convert_status(sc, buf[intrstat]);
>                  ucom_status_change(&sc->sc_ucom);
>              }
>          case USB_ST_SETUP:
>     diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
>     index f26edcebcb9c..2318e6bd0017 100644
>     --- a/sys/dev/usb/usbdevs
>     +++ b/sys/dev/usb/usbdevs
>     @@ -4972,9 +4972,11 @@ product WAVESENSE JAZZ       0xaaaa  Jazz blood
>     glucose meter
>       /* WCH products */
>       product WCH CH341SER       0x5523  CH341/CH340 USB-Serial Bridge
>       product WCH2 CH341SER_2        0x5523  CH341/CH340 USB-Serial Bridge
>     +product WCH2 CH343SER      0x55d3  CH343 USB Serial
>     +product WCH2 CH9102SER     0x55d4  CH9102 USB Serial
>       product WCH2 CH341SER_3        0x7522  CH341/CH340 USB-Serial Bridge
>       product WCH2 CH341SER      0x7523  CH341/CH340 USB-Serial Bridge
>     -product WCH2 U2M       0X752d  CH345 USB2.0-MIDI
>     +product WCH2 U2M       0x752d  CH345 USB2.0-MIDI
> 
>       /* West Mountain Radio products */
>       product WESTMOUNTAIN RIGBLASTER_ADVANTAGE  0x0003  RIGblaster Advantage
>     ------------------------------------------------------------------------------
> 
> 

-- 
Colin Percival
FreeBSD Release Engineering Lead & EC2 platform maintainer
Founder, Tarsnap | www.tarsnap.com | Online backups for the truly paranoid




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?01000197a5a5aff1-ed598ba1-80f2-406b-b11d-fc36e727d9c7-000000>