Date: Mon, 15 Apr 2002 12:56:30 -0700 From: Peter Haight <peterh@sapros.com> To: Nick Hibma <n_hibma@van-laarhoven.org> Cc: hardware@freebsd.org Subject: Re: Reading from the USB ugen device. Message-ID: <200204151956.g3FJuURg037596@wartch.sapros.com>
next in thread | raw e-mail | index | archive | help
>> Ok. But why does this happen: >> >> read(3, 0x8091800, 1024) >> read -1 bytes > >If you print the errno at that point I can tell you. But probably the >errno is ETIMEDOUT, which means that the device told us that there is >no data, so it NACKed the transfer until we got bored. Actually, I'm getting an EIO here. >> At that same point in the protocol if I do: >> read(3, 0x8091800, 64) >> read 64 bytes >> >> I would expect: >> read(3, 0x8091800, 1024) >> read 64 bytes > >I don't know why it reads 64 instead of 1024 bytes. Most probably the >author of the program assumes that he has to do the chunking that is >automatically done by the uhci controller driver. Or maybe I >misunderstood your question. Yeah. I don't think I'm being clear. What's going on at this point is that the program is requesting a bunch of information from the palm pilot about what's on it. These are all very short bulk data transfers. Each set goes like this: write(/dev/ugen0.2, header, 6) (length of next write is in header) write(/dev/ugen0.2, data, 8) read(/dev/ugen0.2, header, 6) read(/dev/ugen0.2, data, 62) (length of this read is read from header) I'll call the 'expected read length' the length I read from the header, not the argument I pass to read(). I'll call the argument I pass to read 'requested read length'. The wierd thing is that if 'expected read length' = 'requested read length' everything works fine, but if 'expected read length' = 64 and 'requested read length' = 1024, it hangs and eventually I get a EIO. I would expect that if I have SHORT_XFER set on /dev/ugen0.2, then I could always set my 'requested read length' to 1024 (i.e. read(/dev/ugen0.2, buffer, 1024)) and that should just always return a buffer that is as long as whatever is read from the bus. (Let's ignore the case where the amount of data is bigger than 1024. That isn't happening. These are all very small amounts of data.) I'll stick the function that I'm using to do the read on the end of this email. Someone else wrote this function and it wasn't working for me as you see it below. To get it to work, I had to change the line: u->iobuflen = read(p->fd, u->iobufp, 1024); to: u->iobuflen = read(p->fd, u->iobufp, len); len is the expected read length. This makes no sense to me. I think it should work with the original function. Thanks for putting up with my inability to explain my problem clearly. static int usb_read(PConnection *p, unsigned char *buf, int len) { /* * We've got to do intermediate buffering of the USB data * from the Visor's bulk endpoint. This is because the kernel * USB driver isn't buffering any data, and we must have a read * operation pending at least as large as the USB transfer size * might potentially be. * * Here, we use a 1024 byte buffer, and return data out of * it. This could return "short" reads to the caller, but * isn't semantically any different than reading an TTY device * which won't return a necessarily predicatable amount of * data. */ struct usb_data *u = p->io_private; int copy_len, retlen = 0; do { /* (?) Return leftover stuff from the previous read. */ if (u->iobuflen > 0) { copy_len = (len > u->iobuflen) ? u->iobuflen : len; memcpy(buf, u->iobufp, copy_len); /* XXX - Potential buffer overflow? */ u->iobufp += copy_len; u->iobuflen -= copy_len; buf += copy_len; len -= copy_len; retlen += copy_len; } if (retlen == 0) { /* (?) There wasn't anything left over from the * last read(). Read some new stuff. */ if (u->iobuflen > 0) { fprintf(stderr, _("usb: trying to fill a non-empty " "buffer.\n")); abort(); } u->iobufp = u->iobuf; u->iobuflen = read(p->fd, u->iobufp, 1024); if (u->iobuflen < 0) { perror("usb read"); return u->iobuflen; } } } while (retlen == 0); return retlen; } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hardware" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200204151956.g3FJuURg037596>