On Wednesday 03 December 2008, Thierry Herbelot wrote:
Hello,
I've been looking at the usb2 code, and from what I've understood, only
synchronous transfers are possible : a read (for exemple) is only scheduled
when the userland program calls usb_bulk_read().
Furthermore, only fixed size buffers are used : only one buffer of 32 kbyte
per transfer. This seems sub-optimal when reading (or writing) from
userland blocks bigger than 32 kbytes, as multiple kernel-to-userland
switches are necessary, and there is a latency window where no buffer
exists to accept data between the arrival of one block and the posting of
the next transfer.
One way to work around this kind of limitations is to provide in advance a
certain number of transfers, arranged in a ring, where the callback
function at the end of a transfer schedules the next, without any further
userland intervention.
Is there any project for adding asynchronous bulk reads and/or writes to
the fine usb2 stack ?
Hi Thierry,
There are two USB API's in the USB2 library. See man libusb20.
The other API supports all of what you want to do. I.E. all of the USB
functionality which is present in the kernel.
--HPS
Example code for the other USB API:
struct libusb20_backend *pbe =
libusb20_be_alloc_default();
struct libusb20_device *pdev = NULL;
while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
if (strstr(libusb20_dev_get_desc(pdev), argv[1]))
{
libusb20_be_dequeue_device(pbe, pdev);
break;
}
}
/* release data */
libusb20_be_free(pbe);
if (pdev == NULL) {
printf(No such device\n);
return (0);
}
printf(Trying to attach ...\n);
if (libusb20_dev_open(pdev, 2)) {
err(1, could not open device);
}
xfer_in = libusb20_tr_get_pointer(pdev, 0);
ep = 0x81;
error = libusb20_tr_open(xfer_in, 65536 /* max block size */, 1 /* #
of transfers */, ep /* endpoint */);
if (error) {
err(1, could not open endpoint %u, %d, ep, error);
}
xfer_out = libusb20_tr_get_pointer(pdev, 1);
ep = 0x01;
error = libusb20_tr_open(xfer_out, 65536, 1, ep);
if (error) {
err(1, could not open endpoint %u, %d, ep, error);
}
usb_pdev = pdev;
libusb20_tr_clear_stall_sync(xfer_in);
libusb20_tr_clear_stall_sync(xfer_out);
do_io(struct libusb20_transfer *xfer, void *buf, uint32_t len, uint32_t
timeout)
{
struct libusb20_device *pdev = usb_pdev;
uint32_t max;
uint32_t alen;
uint32_t slen = 0;
if (libusb20_tr_pending(xfer)) {
return (-1); /* error */
}
repeat:
max = libusb20_tr_get_max_total_length(xfer);
if (max len)
max = len;
//There is also a function to setup multiple bulk transfers at the
//same time. See man libusb20
libusb20_tr_setup_bulk(xfer, buf, max, timeout);
libusb20_tr_start(xfer);
while (libusb20_dev_process(pdev) == 0) {
if (libusb20_tr_pending(xfer) == 0) {
break;
}
// there is also an FD that you can poll!
// See the libusb20_dev_wait_process() code.
libusb20_dev_wait_process(pdev, -1);
}
if (libusb20_tr_get_status(xfer))
return (-1);
alen = libusb20_tr_get_actual_length(xfer);
slen += alen;
if (alen == max) {
len -= alen;
if (len)
goto repeat;
}
return (slen);
}
___
freebsd-usb@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-usb
To unsubscribe, send any mail to [EMAIL PROTECTED]