summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/ucom.c
diff options
context:
space:
mode:
authorakiyama <akiyama@FreeBSD.org>2003-03-09 11:33:26 +0000
committerakiyama <akiyama@FreeBSD.org>2003-03-09 11:33:26 +0000
commitdef74447f31fb89f70132c67b8513f2110cd7492 (patch)
tree720beb049a8c413f2e53e5d56dc9fee0ccc381ec /sys/dev/usb/ucom.c
parent7445c1e8b2fcb05106dc7dd1a13f7f1fe1293444 (diff)
downloadFreeBSD-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.c27
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",
OpenPOWER on IntegriCloud