Re: isoc-in endpoint transfers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 17 Mar 2011, Daniele Capuano wrote:

> Hullo,
> I'm a newbie in kernel development. I'm developing both the host-side
> and the gadget-side of a usb connection, and i'm trying to setup an
> isochronous transfer from the gadget to the host. My application needs
> to allow the gadget to start sending a continuous flow of data
> whenever it wants, thus the host has to wait until data are sent from
> the gadget, and only then it can do its work.
> So, I tryed two scenarios:
> - first, i submitted the urb on the host-side as soon as possible,
> while the gadget submitted isoc urbs only when data were available. In
> this case, the host-side isoc-read callback was executed immediately
> (i.e. the urb seems to complete) but no data was sent (actual_length =
> 0). Both the urb->status and the urb->iso_frame_desc[0].status were
> always zero.

That's not right.  If the gadget isn't sending data then 
iso_frame_desc[n].status should not be 0.  It should be -EPROTO or 
something like that.  If status is 0, it means that the gadget actually 
did send a zero-length packet rather than sending nothing at all.

>  When I started sending data from the gadget, no changes
> happened to the host, even though I noticed that some sporadic buffer
> has been received (one or two times);
> - as the second scenario, I'm trying to let the gadget to start
> sending packets first, while the host waits a little time to start
> receiving. As a consequence, the first two or three buffers are
> correctly received by the host, but then no more data is received
> (i.e. actual_length = 0 and status = 0).

The gadget cannot send any data until the host asks for it.

> I use:
> - a kernel 2.6.31.12 with the RT patch on the host;

What type of host controller?

Why not use a more recent kernel, like 2.6.37?

> - a a kernel 2.6.32-psp on the gadget (i.e. a beagleboard with a
> OMAP3550 core). I used openembedded/bitbake to build the kernel for
> the gadget system.
> 
> I use the following code to initialize the urb (host-side):
> 
>         urb->dev = usb->udev;
>         urb->context = dev;
>         urb->pipe = usb_rcvisocpipe(usb->udev, iso_in->iso_in_endpointAddr);
>         urb->interval = 6;
>         urb->transfer_flags = URB_ISO_ASAP;
>         urb->transfer_buffer = iso_in->iso_in_buffer;
>         urb->complete = thmx_read_iso_callback;
>         urb->number_of_packets = NUM_ISO_PACKETS;
>         urb->transfer_buffer_length = iso_in->iso_in_size;
>         for (i=0; i < NUM_ISO_PACKETS; i++) {
>            urb->iso_frame_desc[i].offset = i;

This is almost certainly wrong.  If NUM_ISO_PACKETS were larger than 1
then the packet buffers would overlap, unless the endpoint's maxpacket
size is 1.  More likely this should be i * iso_in->iso_in_size.

>            urb->iso_frame_desc[i].length = iso_in->iso_in_size;
>         }
> 
> (NUM_ISO_PACKETS is 1). The callback is quite simple:
> 
>    status = urb->iso_frame_desc[0].status;
>    if (status &&
>          !(status == -ENOENT ||
>             status == -ECONNRESET ||
>             status == -ESHUTDOWN)) {
>       dbg("%s - nonzero read isoc status received: %d",
>             __FUNCTION__, status);
>       return;
>    }
>    buf = urb->transfer_buffer;
>    actual_length = urb->iso_frame_desc[0].actual_length;
>    if (actual_length > 0) {
>         /* wake_up_worker_thread() */
>    }
>    retval = usb_submit_urb(urb, GFP_KERNEL);

This is wrong.  Completion callbacks run with interrupts disabled; they 
cannot use GFP_KERNEL.  You must use GFP_ATOMIC.

>    if (retval) {
>       err("%s - failed submitting isoc read urb, error %d",
> __FUNCTION__, retval);
>    }
> 
> on the gadget, i initialized the usb_endpoint_descriptor struct as follows:
> 
> static struct usb_endpoint_descriptor
> hs_iso_in_desc = {
> 	.bLength =		USB_DT_ENDPOINT_SIZE,
> 	.bDescriptorType =	USB_DT_ENDPOINT,
>         .bmAttributes =		USB_ENDPOINT_SYNC_NONE | USB_ENDPOINT_XFER_ISOC,
> 	.wMaxPacketSize =	cpu_to_le16(512),
> 	.bInterval =		6,
> };

What happened to .bEndpointAddress?  You have to specify USB_DIR_IN.

> I suspect that it should be a synchronization issue.

I doubt it.  More likely the gadget code isn't sending the packets 
properly.

>  I also tryed to
> change the USB_ENDPOINT_SYNC_* attribute using SYNC_SYNC but without
> luck... Could someone help me?
> Thanks in advance,

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux