Module Name: src Committed By: snj Date: Wed Dec 14 19:18:58 UTC 2016
Modified Files: src/sys/dev/usb [netbsd-7]: uchcom.c Log Message: Pull up following revision(s) (requested by bouyer in ticket #1321): sys/dev/usb/uchcom.c: revision 1.17 Followling an advice in a linux forum, don't update LCR1/LCR2. With this change this CH340 usb/serial based device: https://www.olimex.com/Products/Breadboarding/BB-CH340T/open-source-hardware (the chip is written H340T) works as expected. As I'm not sure if this is needed for older device, make this change for sc_version 0x30 or newer only. While there, match USB_PRODUCT_WINCHIPHEAD2_CH341_2 too. To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.13.4.1 src/sys/dev/usb/uchcom.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/uchcom.c diff -u src/sys/dev/usb/uchcom.c:1.13 src/sys/dev/usb/uchcom.c:1.13.4.1 --- src/sys/dev/usb/uchcom.c:1.13 Sat Mar 15 19:20:27 2014 +++ src/sys/dev/usb/uchcom.c Wed Dec 14 19:18:58 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: uchcom.c,v 1.13 2014/03/15 19:20:27 martin Exp $ */ +/* $NetBSD: uchcom.c,v 1.13.4.1 2016/12/14 19:18:58 snj Exp $ */ /* * Copyright (c) 2007 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uchcom.c,v 1.13 2014/03/15 19:20:27 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uchcom.c,v 1.13.4.1 2016/12/14 19:18:58 snj Exp $"); /* * driver for WinChipHead CH341/340, the worst USB-serial chip in the world. @@ -91,6 +91,7 @@ int uchcomdebug = 0; #define UCHCOM_REG_LCR2 0x25 #define UCHCOM_VER_20 0x20 +#define UCHCOM_VER_30 0x30 #define UCHCOM_BASE_UNKNOWN 0 #define UCHCOM_BPS_MOD_BASE 20000000 @@ -176,6 +177,7 @@ static const struct uchcom_divider_recor static const struct usb_devno uchcom_devs[] = { { USB_VENDOR_WINCHIPHEAD, USB_PRODUCT_WINCHIPHEAD_CH341SER }, { USB_VENDOR_WINCHIPHEAD2, USB_PRODUCT_WINCHIPHEAD2_CH341 }, + { USB_VENDOR_WINCHIPHEAD2, USB_PRODUCT_WINCHIPHEAD2_CH341_2 }, }; #define uchcom_lookup(v, p) usb_lookup(uchcom_devs, v, p) @@ -570,6 +572,7 @@ update_version(struct uchcom_softc *sc) usbd_errstr(err)); return EIO; } + DPRINTF(("%s: update_version %d\n", device_xname(sc->sc_dev), sc->sc_version)); return 0; } @@ -715,50 +718,52 @@ set_dte_rate(struct uchcom_softc *sc, ui static int set_line_control(struct uchcom_softc *sc, tcflag_t cflag) { - usbd_status err; - uint8_t lcr1val = 0, lcr2val = 0; + if (sc->sc_version < UCHCOM_VER_30) { + usbd_status err; + uint8_t lcr1val = 0, lcr2val = 0; - err = read_reg(sc, UCHCOM_REG_LCR1, &lcr1val, UCHCOM_REG_LCR2, &lcr2val); - if (err) { - aprint_error_dev(sc->sc_dev, "cannot get LCR: %s\n", - usbd_errstr(err)); - return EIO; - } + err = read_reg(sc, UCHCOM_REG_LCR1, &lcr1val, UCHCOM_REG_LCR2, &lcr2val); + if (err) { + aprint_error_dev(sc->sc_dev, "cannot get LCR: %s\n", + usbd_errstr(err)); + return EIO; + } - lcr1val &= ~UCHCOM_LCR1_MASK; - lcr2val &= ~UCHCOM_LCR2_MASK; + lcr1val &= ~UCHCOM_LCR1_MASK; + lcr2val &= ~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. - */ - - switch (ISSET(cflag, CSIZE)) { - case CS5: - case CS6: - case CS7: - return EINVAL; - case CS8: - break; - } + /* + * 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. + */ + + switch (ISSET(cflag, CSIZE)) { + case CS5: + case CS6: + case CS7: + return EINVAL; + case CS8: + break; + } - if (ISSET(cflag, PARENB)) { - lcr1val |= UCHCOM_LCR1_PARENB; - if (ISSET(cflag, PARODD)) - lcr2val |= UCHCOM_LCR2_PARODD; - else - lcr2val |= UCHCOM_LCR2_PAREVEN; - } + if (ISSET(cflag, PARENB)) { + lcr1val |= UCHCOM_LCR1_PARENB; + if (ISSET(cflag, PARODD)) + lcr2val |= UCHCOM_LCR2_PARODD; + else + lcr2val |= UCHCOM_LCR2_PAREVEN; + } - err = write_reg(sc, UCHCOM_REG_LCR1, lcr1val, UCHCOM_REG_LCR2, lcr2val); - if (err) { - aprint_error_dev(sc->sc_dev, "cannot set LCR: %s\n", - usbd_errstr(err)); - return EIO; + err = write_reg(sc, UCHCOM_REG_LCR1, lcr1val, UCHCOM_REG_LCR2, lcr2val); + if (err) { + aprint_error_dev(sc->sc_dev, "cannot set LCR: %s\n", + usbd_errstr(err)); + return EIO; + } } return 0;