ulpt hangs on offline status

Sandy Rutherford sandy at krvarr.bc.ca
Sat Jan 15 02:38:48 PST 2005


Julian,

On Thu, 13 Jan 2005 you wrote:

 > Sandy Rutherford wrote:

 >> 
 >> [root at szamoca:14] usbdevs -v -d
 >> Controller /dev/usb0:
 >> addr 1: full speed, self powered, config 1, UHCI root hub(0x0000), Intel(0x0000), rev 1.00
 >> uhub0
 >> port 1 powered
 >> port 2 addr 2: full speed, power 98 mA, config 1, Centronics connector(0x0006), Entrega(0x1645), rev 1.00
 >> ulpt0
 >> 
 >> I am willing to muck around with the driver to try to fix this myself,
 >> but it would be useful to know if anybody else has seen or worked on
 >> this problem.
 >> 

 > not yet but I'm willing to believe that you may need to poll the device 
 > to see the change in status.
 > That would be handled in the "interrupt" type transfers..
 > We do not support them very well yet.

This evening, I threw a bunch of print statements into ulpt.c to see
what was happening.  This is for /sys/dev/usb/ulpt.c in FreeBSD 4.10.

As expected, it hangs trying to open the connection.

First it runs a tsleep loop:

	for (spin = 0; (ulpt_status(sc) & LPS_SELECT) == 0; spin += STEP) {
		DPRINTF(("ulpt_open: waiting a while\n"));
		if (spin >= TIMEOUT) {
			error = EBUSY;
			sc->sc_state = 0;
			goto done;
		}

		/* wait 1/4 second, give up if we get a signal */
		error = tsleep(sc, LPTPRI | PCATCH, "ulptop", STEP);
		if (error != EWOULDBLOCK) {
			sc->sc_state = 0;
			goto done;
		}

		if (sc->sc_dying) {
			error = ENXIO;
			sc->sc_state = 0;
			goto done;
		}
	}

If the printer is offline, the tsleap returns an EAGAIN (resource
temporarily unavailable) error.  After the loop, it tries to open
input and output pipes.  If any of these fail, `error' is set to one
of EIO or ENOMEM and we `goto done'.

The problem is that if the printer comes back on line during the
tsleep loop, this is not caught and the tsleep loop exits with 
`error == EAGAIN'.  If subsequently, the input and output pipes are
opened successfully, `error' remains set to EAGAIN and this is what
`ulptopen' returns.  It should really return 0, because we have a good
connection and we should start writing data.

Therefore, I stuck the following just before the `done: ' tag:

	/* If we get to here with error == EAGAIN (resource temporarily */
	/* unavailable), it means open out and open in succeeded, even  */
        /* though the tsleep failed.  This probably means that          */
        /* the printer came online during the tsleep loop and we now    */ 
        /* have a connection.  Return 0 to start ulptwrite.             */
        /* --SR sandy at krvarr.bc.ca                                      */
	if (error ==  EAGAIN) {
	  DPRINTF(("error=%d.  Connection established?", error));
	  error = 0;
	}

 done:
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeup(USBDEV(sc->sc_dev));

	DPRINTF(("ulptopen: done, error=%d\n", error));
	return (error);
}


It does the job for me.  ulpt now starts up when the printer comes
back online.

If anybody else has a similar problem, you might try this patch.  I'll
attach a proper patch file below.  If anybody does try this and it messes
something else up, please let me know.  USB devices are notoriously
flakey.

After testing this further for a few days, I'll send in a pr with the
patch.

BTW, I am running FreeBSD on i386 hardware.  The specifics of my USB
setup are:

usbdevs -v
Controller /dev/usb0:
addr 1: full speed, self powered, config 1, UHCI root hub(0x0000), Intel(0x0000), rev 1.00
 port 1 powered
 port 2 addr 2: full speed, power 98 mA, config 1, Centronics connector(0x0006), Entrega(0x1645), rev 1.00

Sandy

 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ulpt.c.patch
Type: application/octet-stream
Size: 805 bytes
Desc: ulpt.c patch
Url : http://lists.freebsd.org/pipermail/freebsd-usb/attachments/20050115/aeab913f/ulpt.c.obj


More information about the freebsd-usb mailing list