From a05d849be393110a4efacb148197434c095e06e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 16 Aug 2018 10:41:54 +0200 Subject: [PATCH 3/5] hw/usb/dev-smartcard-reader: Handle 64 B USB packets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Marc-André Lureau Message-id: <20180816104154.18782-1-marcandre.lureau@redhat.com> Patchwork-id: 81855 O-Subject: [RHEL-7.6 qemu-kvm-rhev PATCH] hw/usb/dev-smartcard-reader: Handle 64 B USB packets Bugzilla: 1589147 RH-Acked-by: Gerd Hoffmann RH-Acked-by: Igor Mammedov RH-Acked-by: Miroslav Rezanina From: Jakub Jelen The current code was not correctly handling 64 B (Max USB 1.1 payload size) packets and therefore preventing some of the messages from smart card to pass through to the guest. If the smart card in host responded with 34 B of data in APDU layer, the CCID headers added up to 64 B. The packet was send, but not correctly committed per USB specification (8.5.3.2 Variable-length Data Stage): > When all of the data structure is returned to the host, the function > should indicate that the Data stage is ended by returning a packet > that is shorter than the MaxPacketSize for the pipe. If the data > structure is an exact multiple of wMaxPacketSize for the pipe, the > function will return a zero-length packet to indicate the end of the > Data stage. This lead the guest applications to timeout while waiting for the rest of data (the emulation layer is answering with NAK until the timeout). This patch is checking the current maximum packet size and if the payload of this size is detected, the message buffer is not yet released. With the next call, the empty buffer is sent and the message buffer is finally released. Signed-off-by: Jakub Jelen Message-id: 20180516115544.3897-2-jjelen@redhat.com Signed-off-by: Gerd Hoffmann (cherry picked from commit 8030dca376fa1bc4d8a6be7628196578f8783ab3) Signed-off-by: Marc-André Lureau Signed-off-by: Miroslav Rezanina --- hw/usb/dev-smartcard-reader.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index e646805..214d3e9 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1064,7 +1064,8 @@ err: return; } -static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p) +static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p, + unsigned int max_packet_size) { int len = 0; @@ -1072,10 +1073,13 @@ static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p) if (s->current_bulk_in != NULL) { len = MIN(s->current_bulk_in->len - s->current_bulk_in->pos, p->iov.size); - usb_packet_copy(p, s->current_bulk_in->data + - s->current_bulk_in->pos, len); + if (len) { + usb_packet_copy(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) { + if (s->current_bulk_in->pos == s->current_bulk_in->len + && len != max_packet_size) { ccid_bulk_in_release(s); } } else { @@ -1107,7 +1111,7 @@ static void ccid_handle_data(USBDevice *dev, USBPacket *p) case USB_TOKEN_IN: switch (p->ep->nr) { case CCID_BULK_IN_EP: - ccid_bulk_in_copy_to_guest(s, p); + ccid_bulk_in_copy_to_guest(s, p, dev->ep_ctl.max_packet_size); break; case CCID_INT_IN_EP: if (s->notify_slot_change) { -- 1.8.3.1