From: Stefan Fritsch <stefan_frit...@genua.de>

An USB transfer must be terminated by a packet that is shorter than
the maximum USB packet size (usually 64Byte) reported by the device
in its descriptor(s). Thus if the last packet of a transfer is exactly
64-Bytes long,  we must send an additional zero length packet.
Fix this for bulk in transfers.

For bulk out transfers this is already ok, for interrupt transfers
this is not a problem as the pipe has a maximum packet size of 8
and transfers are only two bytes long.

Signed-off-by: Stefan Fritsch <stefan_frit...@genua.de>
Signed-off-by: Christian Ehrhardt <christian_ehrha...@genua.de>
---
 hw/usb/dev-smartcard-reader.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 624dc2c447..49791492ea 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1124,7 +1124,13 @@ static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, 
USBPacket *p)
                         s->current_bulk_in->data + s->current_bulk_in->pos,
                         len);
         s->current_bulk_in->pos += len;
-        if (s->current_bulk_in->pos == s->current_bulk_in->len) {
+        /*
+         * The caller assumes that the packet continues if we fill the
+         * entire iov and the iov length matches the max packet size.
+         * Add an empty USB packet in this case.
+         */
+        if (s->current_bulk_in->pos == s->current_bulk_in->len
+            && (len < p->iov.size || p->iov.size < CCID_MAX_PACKET_SIZE)) {
             ccid_bulk_in_release(s);
         }
     } else {
-- 
2.11.0


Reply via email to