laforge has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmo-e1d/+/27579 )
Change subject: usb: Deal with truncated ISO IN transfers
......................................................................
usb: Deal with truncated ISO IN transfers
It seems that in some circumstances, an ISO IN transfer can be
truncated by the bus / host. In such situation we'd currently pass
a non-modulo-32 length to the mux_demux (deframer) code, and it ASSERTs
on that. Let's try to handle this more gracefully by substituting
random garbage and letting higher layers deal with massive bit errors.
Related: OS#5490
Change-Id: Ic453325b93b0e12727625a1495a948d96df4b542
---
M src/usb.c
1 file changed, 24 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-e1d refs/changes/79/27579/1
diff --git a/src/usb.c b/src/usb.c
index 4d30742..074e836 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -201,9 +201,9 @@
{
struct e1_usb_flow *flow = (struct e1_usb_flow *) xfr->user_data;
struct e1_usb_intf_data *id = (struct e1_usb_intf_data *)
flow->line->intf->drv_data;
- int j, rv, len;
+ int j, rv, size;
- len = 0;
+ size = 0;
/* FIXME: Check transfer status ? Error handling ? */
@@ -211,16 +211,34 @@
if (flow->ep & 0x80) {
for (j = 0; j < flow->ppx; j++) {
struct libusb_iso_packet_descriptor *iso_pd = &xfr->iso_packet_desc[j];
+ int len = (int) iso_pd->actual_length;
if (iso_pd->status != LIBUSB_TRANSFER_COMPLETED) {
LOGPLI(flow->line, DE1D, LOGL_ERROR, "IN EP %02x ISO packet %d failed with
status %s\n",
flow->ep, j, get_value_string(libusb_status_str, iso_pd->status));
+ } else if (len > 4 && (len - 4) % 32) {
+ /* some ISO IN packet was truncated. Apparently this
+ * does happen, see
https://osmocom.org/issues/5490 -
+ * there is little we can do here, but instead of the
+ * earlier ASSERT, we just feed some garbage for the
+ * last few timeslots, resulting in bit errors etc. */
+ LOGPLI(flow->line, DE1D, LOGL_ERROR, "IN EP %02x ISO packet %d truncated:
len-4 = %u\n",
+ flow->ep, j, len-4);
+
+ /* The assumption here is that only the last E1 frame is
+ * truncated, as we have no idea how many E1 frames the
+ * USB device firmware wanted to send us. */
+ len += 32 - (len % 32);
+ /* don't overflow the underlying buffer */
+ if (len > (int) iso_pd->length)
+ len = iso_pd->length;
}
+
flow->cb(flow,
libusb_get_iso_packet_buffer_simple(xfr, j),
- (iso_pd->status == LIBUSB_TRANSFER_COMPLETED) ? (int)iso_pd->actual_length :
-1,
+ (iso_pd->status == LIBUSB_TRANSFER_COMPLETED) ? len : -1,
iso_pd->length
);
- len += (iso_pd->length = flow->size);
+ size += (iso_pd->length = flow->size);
}
} else {
for (j = 0; j < flow->ppx; j++) {
@@ -229,12 +247,12 @@
LOGPLI(flow->line, DE1D, LOGL_ERROR, "OUT EP %02x ISO packet %d failed with
status %s\n",
flow->ep, j, get_value_string(libusb_status_str, iso_pd->status));
}
- len += (iso_pd->length = flow->cb(flow, &xfr->buffer[len], flow->size,
flow->size));
+ size += (iso_pd->length = flow->cb(flow, &xfr->buffer[size],
flow->size, flow->size));
}
}
libusb_fill_iso_transfer(xfr, id->devh, flow->ep,
- xfr->buffer, len, flow->ppx,
+ xfr->buffer, size, flow->ppx,
_e1uf_xfr, flow, 0
);
--
To view, visit
https://gerrit.osmocom.org/c/osmo-e1d/+/27579
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-e1d
Gerrit-Branch: master
Gerrit-Change-Id: Ic453325b93b0e12727625a1495a948d96df4b542
Gerrit-Change-Number: 27579
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: newchange