diff --git a/repos/dde_linux/src/drivers/usb/raw/raw.cc b/repos/dde_linux/src/drivers/usb/raw/raw.cc
index ea295ed19d..b469ef76f0 100644
--- a/repos/dde_linux/src/drivers/usb/raw/raw.cc
+++ b/repos/dde_linux/src/drivers/usb/raw/raw.cc
@@ -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)) {
diff --git a/repos/dde_linux/src/drivers/usb_host/raw.cc b/repos/dde_linux/src/drivers/usb_host/raw.cc
index 82930d2c8c..dd542a0f25 100644
--- a/repos/dde_linux/src/drivers/usb_host/raw.cc
+++ b/repos/dde_linux/src/drivers/usb_host/raw.cc
@@ -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)) {
diff --git a/repos/os/include/usb_session/usb_session.h b/repos/os/include/usb_session/usb_session.h
index a097b0ffd7..c987abbd6e 100644
--- a/repos/os/include/usb_session/usb_session.h
+++ b/repos/os/include/usb_session/usb_session.h
@@ -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