diff options
Diffstat (limited to 'sys/dev/usb/serial')
-rw-r--r-- | sys/dev/usb/serial/u3g.c | 12 | ||||
-rw-r--r-- | sys/dev/usb/serial/ubsa.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/ubser.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/uchcom.c | 354 | ||||
-rw-r--r-- | sys/dev/usb/serial/ucycom.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/ufoma.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/uftdi.c | 19 | ||||
-rw-r--r-- | sys/dev/usb/serial/uipaq.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/ulpt.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/umcs.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/umct.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/umodem.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/uplcom.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/usb_serial.c | 127 | ||||
-rw-r--r-- | sys/dev/usb/serial/uslcom.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/serial/uvscom.c | 1 |
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 = ÷rs[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 * |