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 <lafo...@osmocom.org> Gerrit-MessageType: newchange