aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb/serial
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/serial')
-rw-r--r--sys/dev/usb/serial/u3g.c12
-rw-r--r--sys/dev/usb/serial/ubsa.c1
-rw-r--r--sys/dev/usb/serial/ubser.c1
-rw-r--r--sys/dev/usb/serial/uchcom.c354
-rw-r--r--sys/dev/usb/serial/ucycom.c1
-rw-r--r--sys/dev/usb/serial/ufoma.c1
-rw-r--r--sys/dev/usb/serial/uftdi.c19
-rw-r--r--sys/dev/usb/serial/uipaq.c1
-rw-r--r--sys/dev/usb/serial/ulpt.c1
-rw-r--r--sys/dev/usb/serial/umcs.c1
-rw-r--r--sys/dev/usb/serial/umct.c1
-rw-r--r--sys/dev/usb/serial/umodem.c1
-rw-r--r--sys/dev/usb/serial/uplcom.c1
-rw-r--r--sys/dev/usb/serial/usb_serial.c127
-rw-r--r--sys/dev/usb/serial/uslcom.c1
-rw-r--r--sys/dev/usb/serial/uvscom.c1
16 files changed, 318 insertions, 206 deletions
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index e0a1ff29b0a4..a549f93b2af1 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -205,6 +205,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
U3G_DEV(ALINK, 3GU, 0),
U3G_DEV(ALINK, DWM652U5, 0),
U3G_DEV(ALINK, SIM7600E, 0),
+ U3G_DEV(ALINK, SIM7600G, 0),
U3G_DEV(AMOI, H01, 0),
U3G_DEV(AMOI, H01A, 0),
U3G_DEV(AMOI, H02, 0),
@@ -511,21 +512,21 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
U3G_DEV(QUANTA, GLX, 0),
U3G_DEV(QUANTA, Q101, 0),
U3G_DEV(QUANTA, Q111, 0),
+ U3G_DEV(QUECTEL, EC21, 0),
U3G_DEV(QUECTEL, EC25, 0),
U3G_DEV(QUECTEL, EM05, 0),
- U3G_DEV(QUECTEL, EC21, 0),
U3G_DEV(QUECTEL, EG91, 0),
U3G_DEV(QUECTEL, EG95, 0),
+ U3G_DEV(QUECTEL, BG96, 0),
U3G_DEV(QUECTEL, EP06, 0),
U3G_DEV(QUECTEL, EG065K, 0),
- U3G_DEV(QUECTEL, EM12, 0),
- U3G_DEV(QUECTEL, BG96, 0),
- U3G_DEV(QUECTEL, BG95, 0),
- U3G_DEV(QUECTEL, AG35, 0),
U3G_DEV(QUECTEL, AG15, 0),
+ U3G_DEV(QUECTEL, AG35, 0),
U3G_DEV(QUECTEL, AG520, 0),
U3G_DEV(QUECTEL, AG550, 0),
+ U3G_DEV(QUECTEL, EM12, 0),
U3G_DEV(QUECTEL, EM160R, 0),
+ U3G_DEV(QUECTEL, BG95, 0),
U3G_DEV(QUECTEL, RG500, 0),
U3G_DEV(QUECTEL, RG520, 0),
U3G_DEV(QUECTEL, EC200, 0),
@@ -567,6 +568,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
U3G_DEV(SIERRA, MC5728, 0),
U3G_DEV(SIERRA, MC7354, 0),
U3G_DEV(SIERRA, MC7355, 0),
+ U3G_DEV(SIERRA, AC340U, 0),
U3G_DEV(SIERRA, MC7430, 0),
U3G_DEV(SIERRA, MC8700, 0),
U3G_DEV(SIERRA, MC8755, 0),
diff --git a/sys/dev/usb/serial/ubsa.c b/sys/dev/usb/serial/ubsa.c
index 5ff207a17c62..38782d5aef11 100644
--- a/sys/dev/usb/serial/ubsa.c
+++ b/sys/dev/usb/serial/ubsa.c
@@ -26,7 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
diff --git a/sys/dev/usb/serial/ubser.c b/sys/dev/usb/serial/ubser.c
index 91fefceb8240..978639a809be 100644
--- a/sys/dev/usb/serial/ubser.c
+++ b/sys/dev/usb/serial/ubser.c
@@ -64,7 +64,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
/*
* BWCT serial adapter driver
*/
diff --git a/sys/dev/usb/serial/uchcom.c b/sys/dev/usb/serial/uchcom.c
index a61b5a92364c..fdc5515fa722 100644
--- a/sys/dev/usb/serial/uchcom.c
+++ b/sys/dev/usb/serial/uchcom.c
@@ -57,10 +57,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
/*
- * Driver for WinChipHead CH341/340, the worst USB-serial chip in the
- * world.
+ * Driver for WinChipHead CH9102/343/341/340.
*/
#include <sys/stdint.h>
@@ -102,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
@@ -135,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
@@ -151,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,
};
@@ -165,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;
@@ -172,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 */
@@ -226,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;
@@ -245,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,
},
@@ -257,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,
@@ -312,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");
@@ -331,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;
}
@@ -450,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));
}
@@ -517,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);
}
@@ -556,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);
}
/* ----------------------------------------------------------------------
@@ -674,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);
}
@@ -681,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);
}
@@ -738,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]);
@@ -750,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]);
@@ -780,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);
@@ -792,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/serial/ucycom.c b/sys/dev/usb/serial/ucycom.c
index 664cb7f05263..5ab1810a0d11 100644
--- a/sys/dev/usb/serial/ucycom.c
+++ b/sys/dev/usb/serial/ucycom.c
@@ -1,4 +1,3 @@
-#include <sys/cdefs.h>
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
diff --git a/sys/dev/usb/serial/ufoma.c b/sys/dev/usb/serial/ufoma.c
index 66002f57e3b9..3fc6a7a609ba 100644
--- a/sys/dev/usb/serial/ufoma.c
+++ b/sys/dev/usb/serial/ufoma.c
@@ -1,6 +1,5 @@
/* $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ */
-#include <sys/cdefs.h>
#define UFOMA_HANDSFREE
/*-
* SPDX-License-Identifier: BSD-2-Clause
diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c
index 458c6a740f7c..b06dc38432be 100644
--- a/sys/dev/usb/serial/uftdi.c
+++ b/sys/dev/usb/serial/uftdi.c
@@ -31,7 +31,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
/*
* NOTE: all function names beginning like "uftdi_cfg_" can only
* be called from within the config thread function !
@@ -289,8 +288,26 @@ static const STRUCT_USB_HOST_ID uftdi_devs[] = {
UFTDI_DEV(BBELECTRONICS, USPTL4, 0),
UFTDI_DEV(BBELECTRONICS, USTL4, 0),
UFTDI_DEV(BBELECTRONICS, ZZ_PROG1_USB, 0),
+ UFTDI_DEV(BRAINBOXES, US101, 0),
+ UFTDI_DEV(BRAINBOXES, US159, 0),
+ UFTDI_DEV(BRAINBOXES, US235, 0),
UFTDI_DEV(BRAINBOXES, US257, 0),
UFTDI_DEV(BRAINBOXES, US25701, 0),
+ UFTDI_DEV(BRAINBOXES, US279_12, 0),
+ UFTDI_DEV(BRAINBOXES, US279_34, 0),
+ UFTDI_DEV(BRAINBOXES, US279_56, 0),
+ UFTDI_DEV(BRAINBOXES, US279_78, 0),
+ UFTDI_DEV(BRAINBOXES, US313, 0),
+ UFTDI_DEV(BRAINBOXES, US320, 0),
+ UFTDI_DEV(BRAINBOXES, US324, 0),
+ UFTDI_DEV(BRAINBOXES, US346_12, 0),
+ UFTDI_DEV(BRAINBOXES, US346_34, 0),
+ UFTDI_DEV(BRAINBOXES, US701_12, 0),
+ UFTDI_DEV(BRAINBOXES, US701_34, 0),
+ UFTDI_DEV(BRAINBOXES, US842_12, 0),
+ UFTDI_DEV(BRAINBOXES, US842_34, 0),
+ UFTDI_DEV(BRAINBOXES, US842_56, 0),
+ UFTDI_DEV(BRAINBOXES, US842_78, 0),
UFTDI_DEV(CONTEC, COM1USBH, 0),
UFTDI_DEV(DRESDENELEKTRONIK, SENSORTERMINALBOARD, 0),
UFTDI_DEV(DRESDENELEKTRONIK, WIRELESSHANDHELDTERMINAL, 0),
diff --git a/sys/dev/usb/serial/uipaq.c b/sys/dev/usb/serial/uipaq.c
index 2b282009a8bb..f24f1e215767 100644
--- a/sys/dev/usb/serial/uipaq.c
+++ b/sys/dev/usb/serial/uipaq.c
@@ -43,7 +43,6 @@
* Contact isis@cs.umd.edu if you have any questions/comments about this driver
*/
-#include <sys/cdefs.h>
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
diff --git a/sys/dev/usb/serial/ulpt.c b/sys/dev/usb/serial/ulpt.c
index b1e4232ff2a3..ec25ad737596 100644
--- a/sys/dev/usb/serial/ulpt.c
+++ b/sys/dev/usb/serial/ulpt.c
@@ -1,4 +1,3 @@
-#include <sys/cdefs.h>
/* $NetBSD: ulpt.c,v 1.60 2003/10/04 21:19:50 augustss Exp $ */
/*-
diff --git a/sys/dev/usb/serial/umcs.c b/sys/dev/usb/serial/umcs.c
index 18135e3bf67d..8b9b7807ac61 100644
--- a/sys/dev/usb/serial/umcs.c
+++ b/sys/dev/usb/serial/umcs.c
@@ -39,7 +39,6 @@
* quad-port mos7840.
*
*/
-#include <sys/cdefs.h>
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
diff --git a/sys/dev/usb/serial/umct.c b/sys/dev/usb/serial/umct.c
index 4329cf293098..bf6c672907e0 100644
--- a/sys/dev/usb/serial/umct.c
+++ b/sys/dev/usb/serial/umct.c
@@ -1,4 +1,3 @@
-#include <sys/cdefs.h>
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c
index 08d3be554915..59aa5b21e85f 100644
--- a/sys/dev/usb/serial/umodem.c
+++ b/sys/dev/usb/serial/umodem.c
@@ -1,6 +1,5 @@
/* $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ */
-#include <sys/cdefs.h>
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
diff --git a/sys/dev/usb/serial/uplcom.c b/sys/dev/usb/serial/uplcom.c
index 88278ef5790e..1fd73f1f7665 100644
--- a/sys/dev/usb/serial/uplcom.c
+++ b/sys/dev/usb/serial/uplcom.c
@@ -1,6 +1,5 @@
/* $NetBSD: uplcom.c,v 1.21 2001/11/13 06:24:56 lukem Exp $ */
-#include <sys/cdefs.h>
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
diff --git a/sys/dev/usb/serial/usb_serial.c b/sys/dev/usb/serial/usb_serial.c
index 300438010c05..e62bfdb8ff1d 100644
--- a/sys/dev/usb/serial/usb_serial.c
+++ b/sys/dev/usb/serial/usb_serial.c
@@ -29,7 +29,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -151,9 +150,9 @@ static int ucom_unit_alloc(void);
static void ucom_unit_free(int);
static int ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *);
static void ucom_detach_tty(struct ucom_super_softc *, struct ucom_softc *);
-static void ucom_queue_command(struct ucom_softc *,
+static int ucom_queue_command(struct ucom_softc *,
usb_proc_callback_t *, struct termios *pt,
- struct usb_proc_msg *t0, struct usb_proc_msg *t1);
+ struct usb_proc_msg *t0, struct usb_proc_msg *t1, bool wait);
static void ucom_shutdown(struct ucom_softc *);
static void ucom_ring(struct ucom_softc *, uint8_t);
static void ucom_break(struct ucom_softc *, uint8_t);
@@ -593,18 +592,52 @@ ucom_set_usb_mode(struct ucom_super_softc *ssc, enum usb_hc_mode usb_mode)
}
static void
+ucom_command_barrier_cb(struct usb_proc_msg *msg __unused)
+{
+ /* NOP */
+}
+
+/*
+ * ucom_command_barrier inserts a dummy task and waits for it so that we can be
+ * certain that previously enqueued tasks are finished before returning back to
+ * the tty layer.
+ */
+static int
+ucom_command_barrier(struct ucom_softc *sc)
+{
+ struct ucom_super_softc *ssc = sc->sc_super;
+ struct usb_proc_msg dummy = { .pm_callback = ucom_command_barrier_cb };
+ struct usb_proc_msg *task;
+ int error;
+
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
+
+ if (usb_proc_is_gone(&ssc->sc_tq)) {
+ DPRINTF("proc is gone\n");
+ return (ENXIO); /* nothing to do */
+ }
+
+ task = usb_proc_msignal(&ssc->sc_tq, &dummy, &dummy);
+ error = usb_proc_mwait_sig(&ssc->sc_tq, task, task);
+ if (error == 0 && sc->sc_tty != NULL && tty_gone(sc->sc_tty))
+ error = ENXIO;
+ return (error);
+}
+
+static int
ucom_queue_command(struct ucom_softc *sc,
usb_proc_callback_t *fn, struct termios *pt,
- struct usb_proc_msg *t0, struct usb_proc_msg *t1)
+ struct usb_proc_msg *t0, struct usb_proc_msg *t1, bool wait)
{
struct ucom_super_softc *ssc = sc->sc_super;
struct ucom_param_task *task;
+ int error;
UCOM_MTX_ASSERT(sc, MA_OWNED);
if (usb_proc_is_gone(&ssc->sc_tq)) {
DPRINTF("proc is gone\n");
- return; /* nothing to do */
+ return (ENXIO); /* nothing to do */
}
/*
* NOTE: The task cannot get executed before we drop the
@@ -628,8 +661,15 @@ ucom_queue_command(struct ucom_softc *sc,
/*
* Closing or opening the device should be synchronous.
*/
- if (fn == ucom_cfg_close || fn == ucom_cfg_open)
- usb_proc_mwait(&ssc->sc_tq, t0, t1);
+ if (wait) {
+ error = usb_proc_mwait_sig(&ssc->sc_tq, t0, t1);
+
+ /* usb_proc_mwait_sig may have dropped the tty lock. */
+ if (error == 0 && sc->sc_tty != NULL && tty_gone(sc->sc_tty))
+ error = ENXIO;
+ } else {
+ error = 0;
+ }
/*
* In case of multiple configure requests,
@@ -637,6 +677,8 @@ ucom_queue_command(struct ucom_softc *sc,
*/
if (fn == ucom_cfg_start_transfers)
sc->sc_last_start_xfer = &task->hdr;
+
+ return (error);
}
static void
@@ -760,9 +802,8 @@ ucom_open(struct tty *tp)
* example if the device is not present:
*/
error = (sc->sc_callback->ucom_pre_open) (sc);
- if (error) {
- return (error);
- }
+ if (error != 0)
+ goto out;
}
sc->sc_flag |= UCOM_FLAG_HL_READY;
@@ -782,14 +823,21 @@ ucom_open(struct tty *tp)
sc->sc_jitterbuf_in = 0;
sc->sc_jitterbuf_out = 0;
- ucom_queue_command(sc, ucom_cfg_open, NULL,
+ error = ucom_queue_command(sc, ucom_cfg_open, NULL,
&sc->sc_open_task[0].hdr,
- &sc->sc_open_task[1].hdr);
+ &sc->sc_open_task[1].hdr, true);
+ if (error != 0)
+ goto out;
- /* Queue transfer enable command last */
- ucom_queue_command(sc, ucom_cfg_start_transfers, NULL,
- &sc->sc_start_task[0].hdr,
- &sc->sc_start_task[1].hdr);
+ /*
+ * Queue transfer enable command last, we'll have a barrier later so we
+ * don't need to wait on this to complete specifically.
+ */
+ error = ucom_queue_command(sc, ucom_cfg_start_transfers, NULL,
+ &sc->sc_start_task[0].hdr,
+ &sc->sc_start_task[1].hdr, true);
+ if (error != 0)
+ goto out;
if (sc->sc_tty == NULL || (sc->sc_tty->t_termios.c_cflag & CNO_RTSDTR) == 0)
ucom_modem(tp, SER_DTR | SER_RTS, 0);
@@ -800,7 +848,9 @@ ucom_open(struct tty *tp)
ucom_status_change(sc);
- return (0);
+ error = ucom_command_barrier(sc);
+out:
+ return (error);
}
static void
@@ -836,9 +886,9 @@ ucom_close(struct tty *tp)
}
ucom_shutdown(sc);
- ucom_queue_command(sc, ucom_cfg_close, NULL,
+ (void)ucom_queue_command(sc, ucom_cfg_close, NULL,
&sc->sc_close_task[0].hdr,
- &sc->sc_close_task[1].hdr);
+ &sc->sc_close_task[1].hdr, true);
sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_RTS_IFLOW);
@@ -919,11 +969,15 @@ ucom_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
#endif
case TIOCSBRK:
ucom_break(sc, 1);
- error = 0;
+ error = ucom_command_barrier(sc);
+ if (error == ENXIO)
+ error = ENODEV;
break;
case TIOCCBRK:
ucom_break(sc, 0);
- error = 0;
+ error = ucom_command_barrier(sc);
+ if (error == ENXIO)
+ error = ENODEV;
break;
default:
if (sc->sc_callback->ucom_ioctl) {
@@ -1077,10 +1131,13 @@ ucom_line_state(struct ucom_softc *sc,
sc->sc_pls_set |= set_bits;
sc->sc_pls_clr |= clear_bits;
- /* defer driver programming */
- ucom_queue_command(sc, ucom_cfg_line_state, NULL,
- &sc->sc_line_state_task[0].hdr,
- &sc->sc_line_state_task[1].hdr);
+ /*
+ * defer driver programming - we don't propagate any error from
+ * this call because we'll catch such errors further up the call stack.
+ */
+ (void)ucom_queue_command(sc, ucom_cfg_line_state, NULL,
+ &sc->sc_line_state_task[0].hdr,
+ &sc->sc_line_state_task[1].hdr, false);
}
static void
@@ -1236,9 +1293,9 @@ ucom_status_change(struct ucom_softc *sc)
}
DPRINTF("\n");
- ucom_queue_command(sc, ucom_cfg_status_change, NULL,
+ (void)ucom_queue_command(sc, ucom_cfg_status_change, NULL,
&sc->sc_status_task[0].hdr,
- &sc->sc_status_task[1].hdr);
+ &sc->sc_status_task[1].hdr, true);
}
static void
@@ -1310,14 +1367,18 @@ ucom_param(struct tty *tp, struct termios *t)
sc->sc_flag &= ~UCOM_FLAG_GP_DATA;
/* Queue baud rate programming command first */
- ucom_queue_command(sc, ucom_cfg_param, t,
+ error = ucom_queue_command(sc, ucom_cfg_param, t,
&sc->sc_param_task[0].hdr,
- &sc->sc_param_task[1].hdr);
+ &sc->sc_param_task[1].hdr, true);
+ if (error != 0)
+ goto done;
/* Queue transfer enable command last */
- ucom_queue_command(sc, ucom_cfg_start_transfers, NULL,
- &sc->sc_start_task[0].hdr,
- &sc->sc_start_task[1].hdr);
+ error = ucom_queue_command(sc, ucom_cfg_start_transfers, NULL,
+ &sc->sc_start_task[0].hdr,
+ &sc->sc_start_task[1].hdr, true);
+ if (error != 0)
+ goto done;
if (t->c_cflag & CRTS_IFLOW) {
sc->sc_flag |= UCOM_FLAG_RTS_IFLOW;
@@ -1325,6 +1386,8 @@ ucom_param(struct tty *tp, struct termios *t)
sc->sc_flag &= ~UCOM_FLAG_RTS_IFLOW;
ucom_modem(tp, SER_RTS, 0);
}
+
+ error = ucom_command_barrier(sc);
done:
if (error) {
if (opened) {
diff --git a/sys/dev/usb/serial/uslcom.c b/sys/dev/usb/serial/uslcom.c
index 1c27788f77ce..26b937d0b200 100644
--- a/sys/dev/usb/serial/uslcom.c
+++ b/sys/dev/usb/serial/uslcom.c
@@ -1,6 +1,5 @@
/* $OpenBSD: uslcom.c,v 1.17 2007/11/24 10:52:12 jsg Exp $ */
-#include <sys/cdefs.h>
/*
* Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
*
diff --git a/sys/dev/usb/serial/uvscom.c b/sys/dev/usb/serial/uvscom.c
index ee34f0ad3f3d..b9add5c1b37b 100644
--- a/sys/dev/usb/serial/uvscom.c
+++ b/sys/dev/usb/serial/uvscom.c
@@ -1,6 +1,5 @@
/* $NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $ */
-#include <sys/cdefs.h>
/*-
* SPDX-License-Identifier: BSD-2-Clause
*