From owner-svn-src-head@FreeBSD.ORG Mon Oct 19 21:52:02 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 643F81065670; Mon, 19 Oct 2009 21:52:02 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 525418FC0C; Mon, 19 Oct 2009 21:52:02 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n9JLq2kr016358; Mon, 19 Oct 2009 21:52:02 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n9JLq2Hn016355; Mon, 19 Oct 2009 21:52:02 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <200910192152.n9JLq2Hn016355@svn.freebsd.org> From: Andrew Thompson Date: Mon, 19 Oct 2009 21:52:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r198257 - in head/sys/dev/usb: . serial X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Oct 2009 21:52:02 -0000 Author: thompsa Date: Mon Oct 19 21:52:02 2009 New Revision: 198257 URL: http://svn.freebsd.org/changeset/base/198257 Log: Add support for newer WinChipHead CH341 chips, previously in the uch341 driver. Submitted by: HPS Modified: head/sys/dev/usb/serial/uchcom.c head/sys/dev/usb/usbdevs Modified: head/sys/dev/usb/serial/uchcom.c ============================================================================== --- head/sys/dev/usb/serial/uchcom.c Mon Oct 19 21:43:59 2009 (r198256) +++ head/sys/dev/usb/serial/uchcom.c Mon Oct 19 21:52:02 2009 (r198257) @@ -66,7 +66,8 @@ __FBSDID("$FreeBSD$"); /* - * driver for WinChipHead CH341/340, the worst USB-serial chip in the world. + * Driver for WinChipHead CH341/340, the worst USB-serial chip in the + * world. */ #include @@ -206,6 +207,7 @@ static const struct uchcom_divider_recor static const struct usb_device_id uchcom_devs[] = { {USB_VPI(USB_VENDOR_WCH, USB_PRODUCT_WCH_CH341SER, 0)}, + {USB_VPI(USB_VENDOR_WCH2, USB_PRODUCT_WCH2_CH341SER, 0)}, }; /* protypes */ @@ -213,6 +215,7 @@ static const struct usb_device_id uchcom static int uchcom_pre_param(struct ucom_softc *, struct termios *); static void uchcom_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *); +static void uchcom_cfg_open(struct ucom_softc *ucom); static void uchcom_cfg_param(struct ucom_softc *, struct termios *); static void uchcom_cfg_set_break(struct ucom_softc *, uint8_t); static void uchcom_cfg_set_dtr(struct ucom_softc *, uint8_t); @@ -224,12 +227,9 @@ static void uchcom_stop_write(struct uco 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_dtrrts(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_dte_rate(struct uchcom_softc *, uint32_t); -static void uchcom_set_line_control(struct uchcom_softc *, tcflag_t); -static void uchcom_clear_chip(struct uchcom_softc *); -static void uchcom_reset_chip(struct uchcom_softc *); +static void uchcom_set_baudrate(struct uchcom_softc *, uint32_t); static void uchcom_poll(struct ucom_softc *ucom); static device_probe_t uchcom_probe; @@ -275,6 +275,7 @@ static struct ucom_callback uchcom_callb .ucom_cfg_set_dtr = &uchcom_cfg_set_dtr, .ucom_cfg_set_rts = &uchcom_cfg_set_rts, .ucom_cfg_set_break = &uchcom_cfg_set_break, + .ucom_cfg_open = &uchcom_cfg_open, .ucom_cfg_param = &uchcom_cfg_param, .ucom_pre_param = &uchcom_pre_param, .ucom_start_read = &uchcom_start_read, @@ -341,17 +342,6 @@ uchcom_attach(device_t dev) "error=%s\n", usbd_errstr(error)); goto detach; } - /* - * Do the initialization during attach so that the system does not - * sleep during open: - */ - uchcom_update_version(sc); - uchcom_clear_chip(sc); - uchcom_reset_chip(sc); - uchcom_update_status(sc); - - sc->sc_dtr = 1; - sc->sc_rts = 1; /* clear stall at first run */ mtx_lock(&sc->sc_mtx); @@ -458,8 +448,7 @@ uchcom_get_version(struct uchcom_softc * { uint8_t buf[UCHCOM_INPUT_BUF_SIZE]; - uchcom_ctrl_read( - sc, UCHCOM_REQ_GET_VERSION, 0, 0, buf, sizeof(buf)); + uchcom_ctrl_read(sc, UCHCOM_REQ_GET_VERSION, 0, 0, buf, sizeof(buf)); if (rver) *rver = buf[0]; @@ -472,13 +461,13 @@ uchcom_get_status(struct uchcom_softc *s } static void -uchcom_set_dtrrts_10(struct uchcom_softc *sc, uint8_t val) +uchcom_set_dtr_rts_10(struct uchcom_softc *sc, uint8_t val) { uchcom_write_reg(sc, UCHCOM_REG_STAT1, val, UCHCOM_REG_STAT1, val); } static void -uchcom_set_dtrrts_20(struct uchcom_softc *sc, uint8_t val) +uchcom_set_dtr_rts_20(struct uchcom_softc *sc, uint8_t val) { uchcom_ctrl_write(sc, UCHCOM_REQ_SET_DTRRTS, val, 0); } @@ -515,7 +504,7 @@ uchcom_update_status(struct uchcom_softc static void -uchcom_set_dtrrts(struct uchcom_softc *sc) +uchcom_set_dtr_rts(struct uchcom_softc *sc) { uint8_t val = 0; @@ -525,9 +514,9 @@ uchcom_set_dtrrts(struct uchcom_softc *s val |= UCHCOM_RTS_MASK; if (sc->sc_version < UCHCOM_VER_20) - uchcom_set_dtrrts_10(sc, ~val); + uchcom_set_dtr_rts_10(sc, ~val); else - uchcom_set_dtrrts_20(sc, ~val); + uchcom_set_dtr_rts_20(sc, ~val); } static void @@ -583,16 +572,16 @@ found: dp->dv_div = (uint8_t)-div; } - mod = UCHCOM_BPS_MOD_BASE / rate + UCHCOM_BPS_MOD_BASE_OFS; - mod = mod + mod / 2; + mod = (UCHCOM_BPS_MOD_BASE / rate) + UCHCOM_BPS_MOD_BASE_OFS; + mod = mod + (mod / 2); - dp->dv_mod = mod / 0x100; + dp->dv_mod = (mod + 0xFF) / 0x100; return (0); } static void -uchcom_set_dte_rate(struct uchcom_softc *sc, uint32_t rate) +uchcom_set_baudrate(struct uchcom_softc *sc, uint32_t rate) { struct uchcom_divider dv; @@ -607,76 +596,6 @@ uchcom_set_dte_rate(struct uchcom_softc UCHCOM_REG_BPS_PAD, 0); } -static void -uchcom_set_line_control(struct uchcom_softc *sc, tcflag_t cflag) -{ - uint8_t lcr1 = 0; - uint8_t lcr2 = 0; - - uchcom_read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2, &lcr2); - - 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. - */ - - if (cflag & PARENB) { - lcr1 |= UCHCOM_LCR1_PARENB; - if (cflag & PARODD) - lcr2 |= UCHCOM_LCR2_PARODD; - else - lcr2 |= UCHCOM_LCR2_PAREVEN; - } - uchcom_write_reg(sc, UCHCOM_REG_LCR1, lcr1, UCHCOM_REG_LCR2, lcr2); -} - -static void -uchcom_clear_chip(struct uchcom_softc *sc) -{ - DPRINTF("\n"); - uchcom_ctrl_write(sc, UCHCOM_REQ_RESET, 0, 0); -} - -static void -uchcom_reset_chip(struct uchcom_softc *sc) -{ - uint16_t val; - uint16_t idx; - uint8_t lcr1; - uint8_t lcr2; - uint8_t pre; - uint8_t div; - uint8_t mod; - - uchcom_read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2, &lcr2); - uchcom_read_reg(sc, UCHCOM_REG_BPS_PRE, &pre, UCHCOM_REG_BPS_DIV, &div); - uchcom_read_reg(sc, UCHCOM_REG_BPS_MOD, &mod, UCHCOM_REG_BPS_PAD, NULL); - - val = 0; - idx = 0; - 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; - - DPRINTF("reset v=0x%04X, i=0x%04X\n", val, idx); - - uchcom_ctrl_write(sc, UCHCOM_REQ_RESET, val, idx); -} - /* ---------------------------------------------------------------------- * methods for ucom */ @@ -699,7 +618,7 @@ uchcom_cfg_set_dtr(struct ucom_softc *uc DPRINTF("onoff = %d\n", onoff); sc->sc_dtr = onoff; - uchcom_set_dtrrts(sc); + uchcom_set_dtr_rts(sc); } static void @@ -710,7 +629,18 @@ uchcom_cfg_set_rts(struct ucom_softc *uc DPRINTF("onoff = %d\n", onoff); sc->sc_rts = onoff; - uchcom_set_dtrrts(sc); + uchcom_set_dtr_rts(sc); +} + +static void +uchcom_cfg_open(struct ucom_softc *ucom) +{ + struct uchcom_softc *sc = ucom->sc_parent; + + DPRINTF("\n"); + + uchcom_update_version(sc); + uchcom_update_status(sc); } static int @@ -719,12 +649,10 @@ uchcom_pre_param(struct ucom_softc *ucom struct uchcom_divider dv; switch (t->c_cflag & CSIZE) { - case CS5: - case CS6: - case CS7: - return (EIO); - default: + case CS8: break; + default: + return (EIO); } if (uchcom_calc_divider_settings(&dv, t->c_ospeed)) { @@ -738,8 +666,16 @@ uchcom_cfg_param(struct ucom_softc *ucom { struct uchcom_softc *sc = ucom->sc_parent; - uchcom_set_line_control(sc, t->c_cflag); - uchcom_set_dte_rate(sc, t->c_ospeed); + uchcom_get_version(sc, 0); + uchcom_ctrl_write(sc, UCHCOM_REQ_RESET, 0, 0); + uchcom_set_baudrate(sc, t->c_ospeed); + uchcom_read_reg(sc, 0x18, 0, 0x25, 0); + uchcom_write_reg(sc, 0x18, 0x50, 0x25, 0x00); + uchcom_update_status(sc); + uchcom_ctrl_write(sc, UCHCOM_REQ_RESET, 0x501f, 0xd90a); + uchcom_set_baudrate(sc, t->c_ospeed); + uchcom_set_dtr_rts(sc); + uchcom_update_status(sc); } static void @@ -840,14 +776,14 @@ uchcom_write_callback(struct usb_xfer *x tr_setup: pc = usbd_xfer_get_frame(xfer, 0); if (ucom_get_data(&sc->sc_ucom, pc, 0, - UCHCOM_BULK_BUF_SIZE, &actlen)) { + usbd_xfer_max_len(xfer), &actlen)) { DPRINTF("actlen = %d\n", actlen); usbd_xfer_set_frame_len(xfer, 0, actlen); usbd_transfer_submit(xfer); } - return; + break; default: /* Error */ if (error != USB_ERR_CANCELLED) { @@ -855,8 +791,7 @@ tr_setup: usbd_xfer_set_stall(xfer); goto tr_setup; } - return; - + break; } } @@ -871,14 +806,17 @@ uchcom_read_callback(struct usb_xfer *xf switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: - pc = usbd_xfer_get_frame(xfer, 0); - ucom_put_data(&sc->sc_ucom, pc, 0, actlen); + + if (actlen > 0) { + pc = usbd_xfer_get_frame(xfer, 0); + ucom_put_data(&sc->sc_ucom, pc, 0, actlen); + } case USB_ST_SETUP: tr_setup: usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); usbd_transfer_submit(xfer); - return; + break; default: /* Error */ if (error != USB_ERR_CANCELLED) { @@ -886,7 +824,7 @@ tr_setup: usbd_xfer_set_stall(xfer); goto tr_setup; } - return; + break; } } Modified: head/sys/dev/usb/usbdevs ============================================================================== --- head/sys/dev/usb/usbdevs Mon Oct 19 21:43:59 2009 (r198256) +++ head/sys/dev/usb/usbdevs Mon Oct 19 21:52:02 2009 (r198257) @@ -626,6 +626,7 @@ vendor AMIT 0x18c5 AMIT vendor QCOM 0x18e8 Qcom vendor LINKSYS3 0x1915 Linksys vendor QUALCOMMINC 0x19d2 Qualcomm, Incorporated +vendor WCH2 0x1a86 QinHeng Electronics vendor STELERA 0x1a8d Stelera Wireless vendor MPMAN 0x1cae MpMan vendor DRESDENELEKTRONIK 0x1cf1 dresden elektronik @@ -2516,8 +2517,11 @@ product WACOM GRAPHIRE 0x0010 Graphire product WACOM GRAPHIRE3_4X5 0x0013 Graphire 3 4x5 product WACOM INTUOSA5 0x0021 Intuos A5 product WACOM GD0912U 0x0022 Intuos 9x12 Graphics Tablet -/* WCH products*/ + +/* WCH products */ product WCH CH341SER 0x5523 CH341/CH340 USB-Serial Bridge +product WCH2 CH341SER 0x7523 CH341/CH340 USB-Serial Bridge + /* Western Digital products */ product WESTERN COMBO 0x0200 Firewire USB Combo product WESTERN EXTHDD 0x0400 External HDD