From: Thomas J. <tho...@in...> - 2004-06-12 10:06:59
|
Hi! I'm currently using libusb as a basis for libftdi. Libftdi is a library for talking to FTDI's FT232/FT245 type chips. More info here: http://www.intra2net.com/opensource/ftdi/index.html Those chips send two (modem) status bytes for every read. Right now I'm using usb_bulk_read and thought by filtering out the first two bytes of every read was enough. But the status bytes are generate for every URB or every 16ms in the absence of data. -> It can easily happen to have two or more of those status bytes in the usb_bulk_read stream. For testing purposes I've switched my code to real URB processing using usbdevfs + linux ioctls. Works pretty good so far. But I really would like to do this with libusb instead of rolling my own libusb-like-functions. I checked the CVS tree but I haven't seen any support for URB processing. "linux.h" already contains an "usb_urb" structure. What about making this one more generic and add some usb_submit_urb/usb_reap_urb/etc functions? Is this functionality possible for other platforms like MacOS X or FreeBSD libusb currently runs on? Comments are welcome ;-) Cheers, Thomas |
From: Jim P. <ji...@jt...> - 2004-06-12 18:41:32
|
> Those chips send two (modem) status bytes for every read. > Right now I'm using usb_bulk_read and thought by filtering out the > first two bytes of every read was enough. But the status bytes > are generate for every URB or every 16ms in the absence of data. > -> It can easily happen to have two or more of those status bytes > in the usb_bulk_read stream. I believe you always see these status bytes at 64-byte boundaries, ie. at offset 0, 64, 128, 192, etc. in the FTDI data stream. Doing this on the result of usb_bulk_read worked fine for me. -jim |
From: Thomas J. <tho...@in...> - 2004-06-12 18:58:11
|
Hi Jim, > > Those chips send two (modem) status bytes for every read. > > Right now I'm using usb_bulk_read and thought by filtering out the > > first two bytes of every read was enough. But the status bytes > > are generate for every URB or every 16ms in the absence of data. > > -> It can easily happen to have two or more of those status bytes > > in the usb_bulk_read stream. > > I believe you always see these status bytes at 64-byte boundaries, > ie. at offset 0, 64, 128, 192, etc. in the FTDI data stream. > Doing this on the result of usb_bulk_read worked fine for me. Thanks for your reply. On user of libftdi tried this, too, but it wasn't stable. It depends on your readbuffer size and timing as the kernel groups two or more URBs to one request if the usb_bulk_read buffer is big enough. Think about the situation when you don't read fast enough: The status bytes are generated every 16ms in the absence of data. When your next read is f.e. after 48ms, you will have 3x2 status bytes in your stream (which got transfered as 3 single URBs) -> You'll end up with 4 bogus status bytes as only the first two get filtered by the ftdi_read_data function. Cheers, Thomas |
From: Jim P. <ji...@jt...> - 2004-06-12 19:05:48
|
> Think about the situation when you don't read fast enough: The status bytes > are generated every 16ms in the absence of data. When your next read > is f.e. after 48ms, you will have 3x2 status bytes in your stream (which got > transfered as 3 single URBs) -> You'll end up with 4 bogus status bytes > as only the first two get filtered by the ftdi_read_data function. Hmm, maybe. I needed to read with high throughput with as little latency as possible (since the FTDI's tiny send buffer fills up so fast, grr) so I'm sending continuous requests and never hit that problem. -jim |
From: Johannes E. <joh...@er...> - 2004-06-14 18:11:24
|
On Sat, Jun 12, 2004, Thomas Jarosch <tho...@in...> wrote: > Hi Jim, > > > > Those chips send two (modem) status bytes for every read. > > > Right now I'm using usb_bulk_read and thought by filtering out the > > > first two bytes of every read was enough. But the status bytes > > > are generate for every URB or every 16ms in the absence of data. > > > -> It can easily happen to have two or more of those status bytes > > > in the usb_bulk_read stream. > > > > I believe you always see these status bytes at 64-byte boundaries, > > ie. at offset 0, 64, 128, 192, etc. in the FTDI data stream. > > Doing this on the result of usb_bulk_read worked fine for me. > > Thanks for your reply. On user of libftdi tried this, too, but it wasn't > stable. It depends on your readbuffer size and timing as the kernel groups > two or more URBs to one request if the usb_bulk_read buffer is big enough. Actually it doesn't. usb_bulk_read() on Linux will result in one and only one URB being posted. > Think about the situation when you don't read fast enough: The status bytes > are generated every 16ms in the absence of data. When your next read > is f.e. after 48ms, you will have 3x2 status bytes in your stream (which got > transfered as 3 single URBs) -> You'll end up with 4 bogus status bytes > as only the first two get filtered by the ftdi_read_data function. It sounds like the device is buffering those status bytes and sending multiple status packets into one transfer. Perhaps libftdi should handle all of the status bytes? It sounds like what you really wanted are queued transfers, since the data you get is sent every 16ms, you want an URB posted to receive the data when it occurs. JE |
From: Thomas J. <tho...@in...> - 2004-06-14 18:52:37
|
Hi JE, > > > > -> It can easily happen to have two or more of those status bytes > > > > in the usb_bulk_read stream. > > > > > > I believe you always see these status bytes at 64-byte boundaries, > > > ie. at offset 0, 64, 128, 192, etc. in the FTDI data stream. > > > Doing this on the result of usb_bulk_read worked fine for me. > > > > Thanks for your reply. On user of libftdi tried this, too, but it wasn't > > stable. It depends on your readbuffer size and timing as the kernel > > groups two or more URBs to one request if the usb_bulk_read buffer is big > > enough. > > Actually it doesn't. > > usb_bulk_read() on Linux will result in one and only one URB being posted. True that, but atleast the usb_bulk_read function in libusb's linux.c groups together multiple reads if there's enough room in the buffer. > > Think about the situation when you don't read fast enough: The status > > bytes are generated every 16ms in the absence of data. When your next > > read is f.e. after 48ms, you will have 3x2 status bytes in your stream > > (which got transfered as 3 single URBs) -> You'll end up with 4 bogus > > status bytes as only the first two get filtered by the ftdi_read_data > > function. > > It sounds like the device is buffering those status bytes and sending > multiple status packets into one transfer. No, it creates an USB "packet" for each of them. > Perhaps libftdi should handle all of the status bytes? > > It sounds like what you really wanted are queued transfers, since the > data you get is sent every 16ms, you want an URB posted to receive the > data when it occurs. This is only a special case. Those status bytes are in every URB. I'll try something out: I'll reduce libftdi's read buffer size to 64 bytes as this is the maximum size the device will handle internally due to hardware limitations/bugs. After that I remove the do/while stuff from libusb's usb_bulk_read. If everything goes well, it'll work :-) If it works: Is there an API compatible way to add a "only-one-read" flag to usb_bulk_read or would we need another bulk_read_function? (which gets called internally if you use the normal bulk_read) Cheers, Thomas |
From: Johannes E. <joh...@er...> - 2004-06-14 19:14:17
|
On Mon, Jun 14, 2004, Thomas Jarosch <tho...@in...> wrote: > > > > I believe you always see these status bytes at 64-byte boundaries, > > > > ie. at offset 0, 64, 128, 192, etc. in the FTDI data stream. > > > > Doing this on the result of usb_bulk_read worked fine for me. > > > > > > Thanks for your reply. On user of libftdi tried this, too, but it wasn't > > > stable. It depends on your readbuffer size and timing as the kernel > > > groups two or more URBs to one request if the usb_bulk_read buffer is big > > > enough. > > > > Actually it doesn't. > > > > usb_bulk_read() on Linux will result in one and only one URB being posted. > > True that, but atleast the usb_bulk_read function in libusb's linux.c > groups together multiple reads if there's enough room in the buffer. And the device didn't return a short read. > > > Think about the situation when you don't read fast enough: The status > > > bytes are generated every 16ms in the absence of data. When your next > > > read is f.e. after 48ms, you will have 3x2 status bytes in your stream > > > (which got transfered as 3 single URBs) -> You'll end up with 4 bogus > > > status bytes as only the first two get filtered by the ftdi_read_data > > > function. > > > > It sounds like the device is buffering those status bytes and sending > > multiple status packets into one transfer. > > No, it creates an USB "packet" for each of them. I don't see how you can get 6 bytes then. If it's 3 seperate URBs, then your usb_bulk_read() call should only get the first 2 bytes successfully, since it should be a short read and then we'll stop. > > Perhaps libftdi should handle all of the status bytes? > > > > It sounds like what you really wanted are queued transfers, since the > > data you get is sent every 16ms, you want an URB posted to receive the > > data when it occurs. > > This is only a special case. Those status bytes are in every URB. > > I'll try something out: I'll reduce libftdi's read buffer size to 64 bytes as > this is the maximum size the device will handle internally > due to hardware limitations/bugs. After that I remove the do/while stuff > from libusb's usb_bulk_read. If everything goes well, it'll work :-) > > If it works: Is there an API compatible way to add a "only-one-read" flag > to usb_bulk_read or would we need another bulk_read_function? > (which gets called internally if you use the normal bulk_read) We would have to add a new function, but I'm not sure that is necessary right now. JE |
From: Thomas J. <tho...@in...> - 2004-06-14 19:32:14
|
> > > > Think about the situation when you don't read fast enough: The status > > > > bytes are generated every 16ms in the absence of data. When your next > > > > read is f.e. after 48ms, you will have 3x2 status bytes in your > > > > stream (which got transfered as 3 single URBs) -> You'll end up with > > > > 4 bogus status bytes as only the first two get filtered by the > > > > ftdi_read_data function. > > > > > > It sounds like the device is buffering those status bytes and sending > > > multiple status packets into one transfer. > > > > No, it creates an USB "packet" for each of them. > > I don't see how you can get 6 bytes then. > > If it's 3 seperate URBs, then your usb_bulk_read() call should only get > the first 2 bytes successfully, since it should be a short read and then > we'll stop. Doesn't libusb try to issue another IOCTL_USB_BULK if there's enough room in the buffer? Assuming I call libusb's usb_bulk_read with a buffer of 4kb, wouldn't it try to store those 3x 2 byte URBs into this buffer via the do/while loop (linux.c)? Thomas |
From: Johannes E. <joh...@er...> - 2004-06-14 19:49:43
|
On Mon, Jun 14, 2004, Thomas Jarosch <tho...@in...> wrote: > > > > > Think about the situation when you don't read fast enough: The status > > > > > bytes are generated every 16ms in the absence of data. When your next > > > > > read is f.e. after 48ms, you will have 3x2 status bytes in your > > > > > stream (which got transfered as 3 single URBs) -> You'll end up with > > > > > 4 bogus status bytes as only the first two get filtered by the > > > > > ftdi_read_data function. > > > > > > > > It sounds like the device is buffering those status bytes and sending > > > > multiple status packets into one transfer. > > > > > > No, it creates an USB "packet" for each of them. > > > > I don't see how you can get 6 bytes then. > > > > If it's 3 seperate URBs, then your usb_bulk_read() call should only get > > the first 2 bytes successfully, since it should be a short read and then > > we'll stop. > > Doesn't libusb try to issue another IOCTL_USB_BULK if there's enough room > in the buffer? Assuming I call libusb's usb_bulk_read with a buffer of 4kb, > wouldn't it try to store those 3x 2 byte URBs into this buffer > via the do/while loop (linux.c)? } while (ret > 0 && retrieved < size && ret == requested); ret is the number of bytes we just read and requested will be the lesser of MAX_READ_WRITE_SIZE or the size you asked to read. Since we read only 2 bytes, it will not equal requested (which is 4k in your example) and we'll exit. JE |
From: Thomas J. <tho...@in...> - 2004-06-14 20:11:52
|
> > > If it's 3 seperate URBs, then your usb_bulk_read() call should only get > > > the first 2 bytes successfully, since it should be a short read and > > > then we'll stop. > > > > Doesn't libusb try to issue another IOCTL_USB_BULK if there's enough room > > in the buffer? Assuming I call libusb's usb_bulk_read with a buffer of > > 4kb, wouldn't it try to store those 3x 2 byte URBs into this buffer > > via the do/while loop (linux.c)? > > } while (ret > 0 && retrieved < size && ret == requested); > > ret is the number of bytes we just read and requested will be the lesser > of MAX_READ_WRITE_SIZE or the size you asked to read. > > Since we read only 2 bytes, it will not equal requested (which is 4k in > your example) and we'll exit. Sorry, stupid me. Thanks for looking into this! Like I wrote in a previous email, I'll try to change libftdi's internal read buffer size to 64 bytes and see if it helps. (hopefully it does!) Thomas |
From: Thomas J. <tho...@in...> - 2004-06-14 22:28:48
|
> > > > If it's 3 seperate URBs, then your usb_bulk_read() call should only > > > > get the first 2 bytes successfully, since it should be a short read > > > > and then we'll stop. > > > > > > Doesn't libusb try to issue another IOCTL_USB_BULK if there's enough > > > room in the buffer? Assuming I call libusb's usb_bulk_read with a > > > buffer of 4kb, wouldn't it try to store those 3x 2 byte URBs into this > > > buffer via the do/while loop (linux.c)? > > > > } while (ret > 0 && retrieved < size && ret == requested); > > > > ret is the number of bytes we just read and requested will be the lesser > > of MAX_READ_WRITE_SIZE or the size you asked to read. > > > > Since we read only 2 bytes, it will not equal requested (which is 4k in > > your example) and we'll exit. > > Sorry, stupid me. Thanks for looking into this! > Like I wrote in a previous email, I'll try to change libftdi's > internal read buffer size to 64 bytes and see if it helps. > (hopefully it does!) Success! Changing the buffer size to 64 bytes did the trick. The libftdi user tried this earlier but there was another bug in his code which messed up the results :-( Thanks again, Thomas |