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