Index: ulpt.c =================================================================== RCS file: /usr/ncvs/src/sys/dev/usb/ulpt.c,v retrieving revision 1.68 diff -u -r1.68 ulpt.c --- ulpt.c 12 Nov 2005 17:39:31 -0000 1.68 +++ ulpt.c 24 Jan 2006 22:14:17 -0000 @@ -113,7 +113,9 @@ int sc_in; usbd_pipe_handle sc_in_pipe; /* bulk in pipe */ usbd_xfer_handle sc_in_xfer; - void *sc_in_buf; + char *sc_in_buf; /* start of bulk read buffer */ + char *sc_in_bp; /* start of valid data in sc_in_buf */ + int sc_in_len; /* length of valid data at sc_in_bp */ usb_callout_t sc_read_callout; int sc_has_callout; @@ -584,6 +586,8 @@ usb_callout(sc->sc_read_callout, hz/5, ulpt_tick, sc); sc->sc_has_callout = 1; } + sc->sc_in_bp = NULL; + sc->sc_in_len = 0; } sc->sc_state = ULPT_OPEN; @@ -726,33 +730,51 @@ { u_int32_t n, on; int error = 0; - void *bufp; + char *bufp; usbd_xfer_handle xfer; usbd_status err; - DPRINTF(("ulptread\n")); + DPRINTF(("ulptread request %d\n", uio->uio_resid)); if (sc->sc_in_pipe == NULL) return 0; + if (sc->sc_in_len != 0) { + n = min(sc->sc_in_len, uio->uio_resid); + error = uiomove(sc->sc_in_bp, n, uio); + if (error) + return (error); + sc->sc_in_len -= n; + sc->sc_in_bp += n; + if (uio->uio_resid == 0) /* read satisfied */ + return (error); + } xfer = sc->sc_in_xfer; bufp = sc->sc_in_buf; - while ((n = min(ULPT_BSIZE, uio->uio_resid)) != 0) { - DPRINTFN(1, ("ulptread: transfer %d bytes\n", n)); - on = n; + + while (1) { + n = ULPT_BSIZE; err = usbd_bulk_transfer(xfer, sc->sc_in_pipe, USBD_NO_COPY | USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, bufp, &n, "ulptrd"); if (err) { DPRINTF(("ulptread: error=%d\n", err)); - error = EIO; - break; + return (EIO); } - error = uiomove(bufp, n, uio); - if (error) + DPRINTFN(1, ("ulptread: got %d bytes\n", n)); + on = min(n, uio->uio_resid); + error = uiomove(bufp, on, uio); + if (error) { + sc->sc_in_bp = bufp; + sc->sc_in_len = n; break; - if (on != n) + } + if (uio->uio_resid == 0 || n != ULPT_BSIZE) { + /* read satisfied or short read from printer */ + sc->sc_in_bp = bufp + on; + sc->sc_in_len = n - on; break; + } } return (error);