Hi Robert,
sorry for the late reply.
On Tuesday 06 January 2009, Robert Lukassen wrote:
> Hi,
>
> I've noticed that the URB size in case of Bulk transport is set to the
> maximum payload size, or to a limit that is a multiple of the bulk
> packet size (psize * UVC_MAX_ISO_PACKETS). The rationale behind this is
> 'to be consistent with isochronous mode'.
To be honest, the real reason is that I had to set a limit and that value
wasn't really worse than another (at least at that time) :-)
> We encounter some difficulties with this approach. These occur when
> operating Bulk transport over a full-speed link. In that case, the limit
> becomes 64 * 40 = 2560 bytes per URB. The device we use has 16KB
> payloads. The frames typically do not consist of an exact multiple of
> 16KB, so a frame is send as a sequence of 16KB USB bulk transfers,
> ending with a bulk transfer < 16KB.
It's really unfortunate that the USB 2.0 and UVC 1.1 specifications use the
term "payload" for two different concepts.
In USB 2.0, a payload is the data that is carried in the data field of a data
packet within a bus transaction. In UVC 1.1, a Payload Transfer is a unit of
data transfer common to bulk and isochronous endpoints.
Your device has 16kB "payloads". As bulk payloads can be 512 bytes long at
most (in high-speed) mode, I assume you mean UVC payloads (a UVC header
followed by frame data). Is that correct ?
In that case, every 16kB UVC payload should be terminated by a short packet,
not only the last payload.
> According to the USB 2.0 specification a bulk transfer is considered
> done when:
>
> 1) the expected amount of data has been transferred
> 2) a short packet (or zero-length packet) has been transferred
>
> For the device, each of the transfers used to sent full sized payloads
> fall in category 1. 16KB is to be expected by the host, as this is the
> MaxPayloadSize (signalled in the configuration descriptor).
You're mixing USB payloads and UVC payloads. A UVC payload is transferred in a
single bulk transfer, made of multiple bulk data transactions, each carrying
a USB payload. The last data packet of every bulk transfer should be a short
(or zero) packet.
If your device sends 16kB UVC payloads, it should terminate each of them with
a short bulk data packet.
> The device is unaware of the fact that hosts using the UVC driver split
> payload transfers over multiple bulk transfers. If the payload buffer
> size is not an exact multiple of the URB size determined by the UVC
> driver, the host will not be able to detect the end of a payload
> reliably.
The device is unaware of how the host splits a UVC payload across multiple
URBs, but it's aware of how a UVC payload is split across bulk payloads.
> Example:
>
> Assume the frame to be transferred is 100KB. The maximum payload size is
> 16KB. The device will submit 6 16KB payloads and a 4KB final payload.
>
> Because the first 16 KB payload transfers are of category 1, the device
> will not insert a ZLP between the last packet of a payload and the first
> packet of the next payload. The final payload is 4KB, which is a
> multiple of a bulk packet (at either full or high speed), so the device
> will end this payload transfer with a ZLP.
>
> At high speed the UVC driver will issue URBs of 16KB as the limit set by
> psize * UVC_MAX_ISO_PACKETS in that case is 512*40 = 20KB. Each of the
> 16KB payloads is reliably detected because the USB buffer is completely
> full.
>
> The URB transfers reliably detects the bulk transfer end because of the
> ZLP.
>
> At full speed, the UVC driver will submit URBs of 2650 bytes. This means
> that the first 16 KB payload will result in 6 URBS completely filled,
> but the 7th URB will fail to detect the boundary between the two 16KB
> payloads. It will continue to fill the URB until the URB buffer is full
> resulting in an URB that has 1024 bytes of the first payload and 1536
> bytes of the next payload (including its payload header).
>
> This case is not handled in the bulk data decoder I think.
>
> It may seem that ensuring that the payload size is an multiple of the
> URB size might solve this issue. For full sized payloads that is indeed
> the case. Each full sized payload then results in a multiple URBs that
> only contain data for that payload. However, if the last payload
> contains less data than a full sized payload, the device inserts a ZLP
> if the last packet was not short. This because from the device point of
> view, it needs to signal that the host is going to get less data than it
> expects. However, it may happen that the bulk transfer ends at an exact
> multiple of the URB size.
>
> Again, example:
>
> 100 KB frame, 16KB max payload and 2K URB size. The first 6 payload
> transfers all work well. Each payload is transferred with 8 URBs, and
> payload boundaries are detected based on payload buffer being full.
>
> The 7th payload is 4 KB in size. An exact multiple of bulk packets
> completes this transfer, and because 4 KB < 16KB, the device inserts a
> ZLP. The host receives 2 URBs, and then an URB of 0 bytes long (=ZLP).
> Normally, that ZLP would have been absorbed by the USB transport layer
> and caused the URB to end 'prematurely'. But because the UVC host now
> uses a smaller URB buffer lenghth, it needs to handle these ZLP as
> 0-length URBs.
>
> It seems that this is indeed the case, and that 0 length URB would mark
> the end of the payload. So this may be a fix:
>
> In static int uvc_init_video_bulk(struct uvc_video_device *video,
> struct usb_host_endpoint *ep, gfp_t gfp_flags) (uvc_video.c)
>
> psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff;
> size = video->streaming->ctrl.dwMaxPayloadTransferSize;
> video->bulk.max_payload_size = size;
> - if (size > psize * UVC_MAX_ISO_PACKETS)
> - size = psize * UVC_MAX_ISO_PACKETS;
> + if (size > psize * UVC_MAX_ISO_PACKETS) {
> + size = psize * UVC_MAX_ISO_PACKETS;
> + size -= video->bulk.max_payload_size % size;
> + }
> if (uvc_alloc_urb_buffers(video, size) < 0)
>
> I welcome a discussion about this, and a more detailed rationale behind
> the use of UVC_MAX_ISO_PACKETS in this context. Especially since for
> full speed, the packet size difference between bulk and iso transport
> can differ significantly - 64 versus max. 1023. This results in bulk URB
> sizes that are up to 16 times smaller than the ones used for isochronous
> transfer.
Let's first discuss the above confusion between USB and UVC payloads. If it
turns our I was wrong, I'll analyse your patch :-)
Best regards,
Laurent Pinchart
_______________________________________________
Linux-uvc-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/linux-uvc-devel