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

Reply via email to