diff options
author | akiyama <akiyama@FreeBSD.org> | 2003-03-09 11:33:26 +0000 |
---|---|---|
committer | akiyama <akiyama@FreeBSD.org> | 2003-03-09 11:33:26 +0000 |
commit | def74447f31fb89f70132c67b8513f2110cd7492 (patch) | |
tree | 720beb049a8c413f2e53e5d56dc9fee0ccc381ec /sys/dev/usb/ucom.c | |
parent | 7445c1e8b2fcb05106dc7dd1a13f7f1fe1293444 (diff) | |
download | FreeBSD-src-def74447f31fb89f70132c67b8513f2110cd7492.zip FreeBSD-src-def74447f31fb89f70132c67b8513f2110cd7492.tar.gz |
Fix page fault with FTDI's USB serial device.
Fix lost characters counting.
Move setting receiver state to proper place on ucomstopread().
Diffstat (limited to 'sys/dev/usb/ucom.c')
-rw-r--r-- | sys/dev/usb/ucom.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/sys/dev/usb/ucom.c b/sys/dev/usb/ucom.c index c25bc39..6f8d525 100644 --- a/sys/dev/usb/ucom.c +++ b/sys/dev/usb/ucom.c @@ -974,6 +974,11 @@ ucomwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); DPRINTF(("ucomwritecb: cc = %d\n", cc)); + if (cc <= sc->sc_opkthdrlen) { + printf("%s: sent size too small, cc = %d\n", + USBDEVNAME(sc->sc_dev), cc); + goto error; + } /* convert from USB bytes to tty bytes */ cc -= sc->sc_opkthdrlen; @@ -1049,10 +1054,21 @@ ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) usbd_get_xfer_status(xfer, NULL, (void **)&cp, &cc, NULL); DPRINTF(("ucomreadcb: got %d chars, tp = %p\n", cc, tp)); + if (cc == 0) + goto resubmit; + if (sc->sc_callback->ucom_read != NULL) sc->sc_callback->ucom_read(sc->sc_parent, sc->sc_portno, &cp, &cc); + if (cc > sc->sc_ibufsize) { + printf("%s: invalid receive data size, %d chars\n", + USBDEVNAME(sc->sc_dev), cc); + goto resubmit; + } + if (cc < 1) + goto resubmit; + s = spltty(); if (tp->t_state & TS_CAN_BYPASS_L_RINT) { if (tp->t_rawq.c_cc + cc > tp->t_ihiwat @@ -1075,18 +1091,21 @@ ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) lostcc); } else { /* Give characters to tty layer. */ - while (cc-- > 0) { - DPRINTFN(7,("ucomreadcb: char = 0x%02x\n", *cp)); - if ((*rint)(*cp++, tp) == -1) { + while (cc > 0) { + DPRINTFN(7, ("ucomreadcb: char = 0x%02x\n", *cp)); + if ((*rint)(*cp, tp) == -1) { /* XXX what should we do? */ printf("%s: lost %d chars\n", USBDEVNAME(sc->sc_dev), cc); break; } + cc--; + cp++; } } splx(s); + resubmit: err = ucomstartread(sc); if (err) { printf("%s: read start failed\n", USBDEVNAME(sc->sc_dev)); @@ -1132,11 +1151,11 @@ ucomstopread(struct ucom_softc *sc) DPRINTF(("ucomstopread: enter\n")); if (!(sc->sc_state & UCS_RXSTOP)) { + sc->sc_state |= UCS_RXSTOP; if (sc->sc_bulkin_pipe == NULL) { DPRINTF(("ucomstopread: bulkin pipe NULL\n")); return; } - sc->sc_state |= UCS_RXSTOP; err = usbd_abort_pipe(sc->sc_bulkin_pipe); if (err) { DPRINTF(("ucomstopread: err = %s\n", |