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;

Attachment: 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

Reply via email to