usb_host: properly handle ISOC read requests

* Update the 'packet_size' information with the actual length for
  each isoc frame to be able to handle short reads at the client side.

* Copy the whole transfer buffer because the host controller stores
  the data at the original offsets, i.e., the buffer is not densely
  packed.

Fixes #4018.
This commit is contained in:
Josef Söntgen 2021-01-28 14:37:59 +01:00 committed by Norman Feske
parent b51ae104c2
commit a6f0b05834
3 changed files with 27 additions and 4 deletions

View File

@ -278,9 +278,20 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
p.transfer.actual_size = urb->actual_length;
p.succeded = true;
if (read)
if (read) {
/* make sure the client sees the actual amount of data */
for (int i = 0; i < urb->number_of_packets; i++) {
p.transfer.actual_packet_size[i] = urb->iso_frame_desc[i].actual_length;
}
/*
* We have to copy the whole transfer buffer because the
* controller used the offsets into the original buffer to
* store the data.
*/
Genode::memcpy(_sink->packet_content(p), urb->transfer_buffer,
urb->actual_length);
urb->transfer_buffer_length);
}
} else if (urb->status == -ESHUTDOWN) {
p.error = Packet_descriptor::NO_DEVICE_ERROR;
} else if ((urb->status == -EPROTO) || (urb->status == -EILSEQ)) {

View File

@ -286,9 +286,20 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
p.transfer.actual_size = urb->actual_length;
p.succeded = true;
if (read)
if (read) {
/* make sure the client sees the actual amount of data */
for (int i = 0; i < urb->number_of_packets; i++) {
p.transfer.actual_packet_size[i] = urb->iso_frame_desc[i].actual_length;
}
/*
* We have to copy the whole transfer buffer because the
* controller used the offsets into the original buffer to
* store the data.
*/
Genode::memcpy(_sink->packet_content(p), urb->transfer_buffer,
urb->actual_length);
urb->transfer_buffer_length);
}
} else if (urb->status == -ESHUTDOWN) {
p.error = Packet_descriptor::NO_DEVICE_ERROR;
} else if ((urb->status == -EPROTO) || (urb->status == -EILSEQ)) {

View File

@ -68,6 +68,7 @@ struct Usb::Packet_descriptor : Genode::Packet_descriptor
int polling_interval; /* for interrupt transfers */
int number_of_packets;
size_t packet_size[MAX_PACKETS];
size_t actual_packet_size[MAX_PACKETS];
} transfer;
struct