提交 b17ea167 编写于 作者: P Pete Zaitcev 提交者: Greg Kroah-Hartman

usbmon: correct length for isochronous

Usually the usbmon returns the amount of data specified in
urb->transfer_buffer_length for output submissions and urb->actual_length
for input callbacks. However, for Isochronous input transfers, this is
not enough, since the returned data buffer may contain "holes".

One easy way to fix this is to use urb->transfer_buffer_length,
but this often transfers a whole lot of unused data, so we find
how much was actually used instead.

Original patch by Márton Németh. See also kernel bug 22182.
Signed-off-by: NPete Zaitcev <zaitcev@redhat.com>
Signed-off-by: NMárton Németh <nm127@freemail.hu>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 4f683843
...@@ -437,6 +437,28 @@ static unsigned int mon_bin_get_data(const struct mon_reader_bin *rp, ...@@ -437,6 +437,28 @@ static unsigned int mon_bin_get_data(const struct mon_reader_bin *rp,
return length; return length;
} }
/*
* This is the look-ahead pass in case of 'C Zi', when actual_length cannot
* be used to determine the length of the whole contiguous buffer.
*/
static unsigned int mon_bin_collate_isodesc(const struct mon_reader_bin *rp,
struct urb *urb, unsigned int ndesc)
{
struct usb_iso_packet_descriptor *fp;
unsigned int length;
length = 0;
fp = urb->iso_frame_desc;
while (ndesc-- != 0) {
if (fp->actual_length != 0) {
if (fp->offset + fp->actual_length > length)
length = fp->offset + fp->actual_length;
}
fp++;
}
return length;
}
static void mon_bin_get_isodesc(const struct mon_reader_bin *rp, static void mon_bin_get_isodesc(const struct mon_reader_bin *rp,
unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc) unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc)
{ {
...@@ -479,6 +501,10 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, ...@@ -479,6 +501,10 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
/* /*
* Find the maximum allowable length, then allocate space. * Find the maximum allowable length, then allocate space.
*/ */
urb_length = (ev_type == 'S') ?
urb->transfer_buffer_length : urb->actual_length;
length = urb_length;
if (usb_endpoint_xfer_isoc(epd)) { if (usb_endpoint_xfer_isoc(epd)) {
if (urb->number_of_packets < 0) { if (urb->number_of_packets < 0) {
ndesc = 0; ndesc = 0;
...@@ -487,14 +513,16 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, ...@@ -487,14 +513,16 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
} else { } else {
ndesc = urb->number_of_packets; ndesc = urb->number_of_packets;
} }
if (ev_type == 'C' && usb_urb_dir_in(urb))
length = mon_bin_collate_isodesc(rp, urb, ndesc);
} else { } else {
ndesc = 0; ndesc = 0;
} }
lendesc = ndesc*sizeof(struct mon_bin_isodesc); lendesc = ndesc*sizeof(struct mon_bin_isodesc);
urb_length = (ev_type == 'S') ? /* not an issue unless there's a subtle bug in a HCD somewhere */
urb->transfer_buffer_length : urb->actual_length; if (length >= urb->transfer_buffer_length)
length = urb_length; length = urb->transfer_buffer_length;
if (length >= rp->b_size/5) if (length >= rp->b_size/5)
length = rp->b_size/5; length = rp->b_size/5;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册