*** src/sys/dev/usb/ugen.c.lfc Mon Dec 22 01:33:26 2003 --- src/sys/dev/usb/ugen.c Fri Dec 26 13:16:06 2003 *************** *** 66,71 **** --- 66,72 ---- #include #include + #define USB_DEBUG #ifdef USB_DEBUG #define DPRINTF(x) if (ugendebug) logprintf x #define DPRINTFN(n,x) if (ugendebug>(n)) logprintf x *************** *** 93,98 **** --- 94,100 ---- int state; #define UGEN_ASLP 0x02 /* waiting for data */ #define UGEN_SHORT_OK 0x04 /* short xfers are OK */ + #define UGEN_CLEAR_STALL 0x08 /* perform clear stall on next read */ usbd_pipe_handle pipeh; struct clist q; struct selinfo rsel; *************** *** 506,511 **** --- 508,537 ---- } Static int + ugen_clear_halt(struct ugen_endpoint *sce) + { + usbd_status err; + int error = 0; + + err = usbd_clear_endpoint_stall(sce->pipeh); + if (err) { + if (err == USBD_INTERRUPTED) { + DPRINTFN(10, ("ugen_clear_halt: interrupted\n")); + error = EINTR; + } else if (err == USBD_TIMEOUT) { + DPRINTFN(10, ("ugen_clear_halt: time out\n")); + error = ETIMEDOUT; + } else { + DPRINTFN(10, ("ugen_clear_halt: I/O Error(%d)\n", + err)); + error = EIO; + } + } + + return(error); + } + + Static int ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag) { struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN]; *************** *** 575,585 **** } break; case UE_BULK: xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == 0) return (ENOMEM); while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { ! DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n)); tn = n; err = usbd_bulk_transfer( xfer, sce->pipeh, --- 601,620 ---- } break; case UE_BULK: + if (sce->state & UGEN_CLEAR_STALL) { + DPRINTF(("ugenread: clearing endpoint halt on ioctl\n")); + sce->state &= (~UGEN_CLEAR_STALL); + if (ugen_clear_halt(sce)) { + printf("ugenread: endpoint clear failed\n"); + } + return (0); + } xfer = usbd_alloc_xfer(sc->sc_udev); if (xfer == 0) return (ENOMEM); + tn = 0; while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { ! DPRINTFN(1, ("ugenread: start transfer %d bytes%s timeout=%d\n",n,sce->state & UGEN_SHORT_OK ? " shortok" : "",sce->timeout)); tn = n; err = usbd_bulk_transfer( xfer, sce->pipeh, *************** *** 595,605 **** error = EIO; break; } ! DPRINTFN(1, ("ugenread: got %d bytes\n", tn)); error = uiomove(buf, tn, uio); if (error || tn < n) break; } usbd_free_xfer(xfer); break; case UE_ISOCHRONOUS: --- 630,648 ---- error = EIO; break; } ! DPRINTFN(1, ("ugenread: got %d bytes start=0x%x\n", tn, (int) buf[0])); error = uiomove(buf, tn, uio); if (error || tn < n) break; } + #if 0 + if (tn == 0 || tn == n) { + DPRINTF(("ugenread: clearing endpoint halt\n")); + if (ugen_clear_halt(sce)) { + printf("ugenread: endpoint clear failed\n"); + } + } + #endif usbd_free_xfer(xfer); break; case UE_ISOCHRONOUS: *************** *** 1045,1050 **** --- 1088,1108 ---- switch (cmd) { case FIONBIO: /* All handled in the upper FS layer. */ + return (0); + case USB_CLEAR_ENDPOINT_STALL: + sce = &sc->sc_endpoints[endpt][IN]; + if (sce == NULL) + return (EINVAL); + #ifdef DIAGNOSTIC + if (sce->pipeh == NULL) { + printf("ugenioctl: USB_CLEAR_ENDPOINT_STALL, no pipe\n"); + return (EIO); + } + #endif + sce->state |= UGEN_CLEAR_STALL; + /* causes panic at present... + usbd_clear_endpoint_stall(sce->pipeh); + */ return (0); case USB_SET_SHORT_XFER: /* This flag only affects read */ *** src/sys/dev/usb/usb.h.lfc Mon Dec 22 01:34:44 2003 --- src/sys/dev/usb/usb.h Mon Dec 22 01:45:39 2003 *************** *** 562,567 **** --- 562,568 ---- #define USB_GET_DEVICEINFO _IOR ('U', 112, struct usb_device_info) #define USB_SET_SHORT_XFER _IOW ('U', 113, int) #define USB_SET_TIMEOUT _IOW ('U', 114, int) + #define USB_CLEAR_ENDPOINT_STALL _IOW ('U', 115, int) /* Modem device */ #define USB_GET_CM_OVER_DATA _IOR ('U', 130, int)