On Sat, Dec 11, 2010 at 08:14:24PM +0100, Mark Kettenis wrote:
> > Date: Wed, 8 Dec 2010 06:07:30 +0000
> > From: Jacob Meuser <jake...@sdf.lonestar.org>
> > 
> > I recently got a hp officejet 4500.  it's a 3-in-1 printer/scanner/fax.
> > printing works great with the hplip packages.  scanning doesn't work at
> > all.
> > 
> > I tracked the problem to read() failing in usb_bulk_read() in libusb.
> > errno was EINTR.  so I made this function just continue when read() got
> > EINTR.  I could then scan, but not very reliably.
> > 
> > so I went into the kernel, and tracked it to usbdi_util.c:
> > 
> > @ usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_ha
> > 
> >     error = tsleep((caddr_t)xfer, PZERO | PCATCH, lbl, 0);
> >     splx(s);
> >     if (error) {
> >             DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error));
> >             usbd_abort_pipe(pipe);
> >             return (USBD_INTERRUPTED);
> >     }
> > 
> > on a hunch, I changed 'PZERO | PCATCH' to 'PWAIT'.  then scanning became
> > 100% reliable.  even full-page 1200dpi (~525MB of data) worked
> > perfectly.
> > 
> > great.  but, what if we need to interrupt the transfer.  we don't want
> > to hang here.
> > 
> > well, this function takes a timeout.  so, it's possible to make it
> > return, even if the transfer stalls.  but is this used?  I looked
> > at the ports that use libusb.  setting 0/infinite timeout for bulk
> > transfers is extremely rare, only set in code marked experimental
> > or problematic.  in the kernel, there are however some callers that
> > use USBD_NO_TIMEOUT.
> > 
> > so, I offer the following.  if there's no timeout, behave like we do
> > now and catch signals, and if there's a timeout, ignore signals.
> > 
> > I did the same for interrupt transfers because the situation seems
> > to be the same.
> > 
> > thoughts?
> 
> Sorry, but this very much feels like you're hacking around a bug in
> the application you're using.  If it installs signal handler without
> specifying the SA_RESTART flag, it has to deal with read(2) failing
> with EINTR.

that application would be libusb itself.  is a library supposed
to be messing with signals?


> > Index: usbdi_util.c
> > ===================================================================
> > RCS file: /cvs/src/sys/dev/usb/usbdi_util.c,v
> > retrieving revision 1.25
> > diff -u -p usbdi_util.c
> > --- usbdi_util.c    26 Jun 2008 05:42:19 -0000      1.25
> > +++ usbdi_util.c    8 Dec 2010 04:58:49 -0000
> > @@ -426,7 +426,7 @@ usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_ha
> >      u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size, char 
> > *lbl)
> >  {
> >     usbd_status err;
> > -   int s, error;
> > +   int s, error, pri;
> >  
> >     usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout,
> >         usbd_bulk_transfer_cb);
> > @@ -437,7 +437,8 @@ usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_ha
> >             splx(s);
> >             return (err);
> >     }
> > -   error = tsleep((caddr_t)xfer, PZERO | PCATCH, lbl, 0);
> > +   pri = timeout == USBD_NO_TIMEOUT ? (PZERO | PCATCH) : PWAIT;
> > +   error = tsleep((caddr_t)xfer, pri, lbl, 0);
> >     splx(s);
> >     if (error) {
> >             DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error));
> > @@ -467,7 +468,7 @@ usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_ha
> >      u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size, char 
> > *lbl)
> >  {
> >     usbd_status err;
> > -   int s, error;
> > +   int s, error, pri;
> >  
> >     usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout,
> >         usbd_intr_transfer_cb);
> > @@ -478,7 +479,8 @@ usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_ha
> >             splx(s);
> >             return (err);
> >     }
> > -   error = tsleep(xfer, PZERO | PCATCH, lbl, 0);
> > +   pri = timeout == USBD_NO_TIMEOUT ? (PZERO | PCATCH) : PWAIT;
> > +   error = tsleep(xfer, pri, lbl, 0);
> >     splx(s);
> >     if (error) {
> >             DPRINTF(("usbd_intr_transfer: tsleep=%d\n", error));

-- 
jake...@sdf.lonestar.org
SDF Public Access UNIX System - http://sdf.lonestar.org

Reply via email to