On Thu, 23 Aug 2007, Charles Lepple wrote: > On 8/22/07, Daniel O'Connor <[EMAIL PROTECTED]> wrote: > > On Wed, 22 Aug 2007, Charles Lepple wrote: > > > NUT drivers poll the UPS every so often, which works fine on > > > systems where a single libusb call results in a single USB > > > transaction. In FreeBSD (and probably other BSD systems as well), > > > interrupt transfers are scheduled periodically, even if the > > > calling program is not requesting interrupt transfers at the same > > > rate. > > > > I had a look through the USB code and it seems that ugen uses the > > default value which means that it obtains the value from the end > > point descriptor. > > Right. IIRC, Linux and Windows only poll the device as often as the > userspace program or kernel driver request an interrupt transfer.
So does the USB device not have a problem with the endpoint not being serviced for a time? (Apparently not :) In any case it shouldn't matter IMO - if the kernel buffer is full it should make no difference it should just mean that the endpoint goes unread for a little while and when userland catches up the kernel starts reading again. Perhaps the kernel wrongly marks the interface as broken/stalled/whatever when its buffer fills up, or it reads a partial message and fills the buffer - that would mean subsequent reads are being confused.. Looking at the way ugenintr does it I think the second one is certainly possible.. I don't really know much about clists though so I am not sure if it's possible to tell how much free space is available in one (so you could discard the whole packet if there is not enough room to hold it all) The attached patch will log when this happens and remove data from the end of the packet.. Ideally I'd check for the amount of free space before putting stuff there but I don't know how to do that :) Would someone be able to test it? I don't have a USB UPS here at the moment, it requires patching your kernel and reloading ugen.ko (at least, probably need to reboot if it's in your kernel) Note that the diff is against HEAD but should be easy to apply manually. > Probably the best thing would be to have the kernel driver only > commit to the buffer in multiples of the interrupt transfer size. The > OMNIVS1000 sends 8-byte packets over the interrupt IN pipe, and stuff > would occasionally get misaligned by 4 bytes (in a test program that > repeatedly read 8 bytes from the interrupt endpoint via libusb). Ahah, I just read this after writing the above :) -- Daniel O'Connor software and network engineer for Genesis Software - http://www.gsoft.com.au "The nice thing about standards is that there are so many of them to choose from." -- Andrew Tanenbaum GPG Fingerprint - 5596 B766 97C0 0E94 4347 295E E593 DC20 7B3F CE8C
Index: dev/usb/ugen.c
===================================================================
RCS file: /usr/CVS-Repository/src/sys/dev/usb/ugen.c,v
retrieving revision 1.111
diff -u -r1.111 ugen.c
--- dev/usb/ugen.c 28 Jun 2007 06:22:40 -0000 1.111
+++ dev/usb/ugen.c 23 Aug 2007 05:02:51 -0000
@@ -1008,7 +1008,8 @@
/*struct ugen_softc *sc = sce->sc;*/
u_int32_t count;
u_char *ibuf;
-
+ int i;
+
if (status == USBD_CANCELLED)
return;
@@ -1027,7 +1028,11 @@
DPRINTFN(5, (" data = %02x %02x %02x\n",
ibuf[0], ibuf[1], ibuf[2]));
- (void)b_to_q(ibuf, count, &sce->q);
+ if ((i = b_to_q(ibuf, count, &sce->q)) > 0) {
+ printf("ugenintr: Unable to copy %d bytes onto clist, unputc'ing\n", i);
+ while (i-- > 0)
+ (void)unputc(&sce->q);
+ }
if (sce->state & UGEN_ASLP) {
sce->state &= ~UGEN_ASLP;
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ Nut-upsuser mailing list [email protected] http://lists.alioth.debian.org/mailman/listinfo/nut-upsuser

