Subject: ulpt(4) and non-blocking read
To: None <firstname.lastname@example.org>
From: Greg Troxel <email@example.com>
Date: 12/28/2007 19:48:19
The USB printer driver supports reading, but doesn't support nonblocking
IO, which means it doesn't work with gutenprint. I have posted a
similar note to the gutenprint list.
Does anyone feel ownership of src/sys/dev/ulpt.c?
Invoking a bulk transfer on an input endpoint can have side effects on
some devices, so some drivers avoid such reads unless a read operation
has been invoked. On other devices, queuing a read transfer is normal.
So: on USB printers, is it ok to start a read bulk transfer just because
the device is open?
There are two approaches:
1) On a read system call, if there is any data already read, return it.
If not, invoke a read bulk transfer, and if it completes very quickly
return the data. If not, return EWOULDBLOCK. This perhaps fudges a bit
on non-blocking vs fast.
2) On open, start a read transfer, and as each transfer completes, if
there is room in the input buffer, start a new one. On a read system
call, return whatever data is already in the buffer (and therefore start
a read transfer if space is newly freed).
Besides non-blocking reads, there's the issue of select/poll for read.
To make this work, I think approach #2 is needed, because if no read
transfer has been done, there's no way to know if there's data.
Linux's drivers/usb/class/usblp.c seems to do a blend of these, starting
a transfer on read, and restarting one on completion, but not starting
one on the open call.
NetBSD and FreeBSD both fail to support nonblocking read at all.
OpenBSD seems to have an older ulpt that does not support reading at all.
Opensolaris appears not to support nonblocking reads, but I could be
wrong as I am not familiar with the codebase.
Option 1 is easier, and could probably be done by modifying the existing
loop to return after the first iteration whether the transfer succeeds
or not. So I'll probably try that first.
Any comments on the approach, or pointing out any confusion on my part,
would be appreciated.