[PATCH 10/27] hw/usb/dev-smartcard-reader: reset all I/O state on device reset

Marc-AndrĂ© Lureau <[email protected]> Wed, 05 Aug 2026 15:51:00 +0400
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
Clear bulk-in entries (len/pos), current_bulk_in pointer, bulk-out
position, error status, and protocol parameters during reset. Previously
only the bulk-in ring buffer indices and pending answers were cleared,
leaving stale state that could corrupt subsequent transfers.

Move ccid_reset() after its callees to avoid forward declarations.

Drop redundant initialization from realize() since it calls reset().

Fixes: 367071447ec5 ("usb-ccid: add CCID bus")
Signed-off-by: Marc-AndrĂ© Lureau <[email protected]>
---
 hw/usb/dev-smartcard-reader.c | 60 +++++++++++++++++++++++--------------------
 1 file changed, 32 insertions(+), 28 deletions(-)

diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index bed641be4512..12c82c8f6458 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -574,9 +574,16 @@ static void ccid_remove_pending_answer(USBCCIDState *s,
 
 static void ccid_bulk_in_clear(USBCCIDState *s)
 {
+    int i;
+
+    for (i = 0; i < BULK_IN_PENDING_NUM; i++) {
+        s->bulk_in_pending[i].len = 0;
+        s->bulk_in_pending[i].pos = 0;
+    }
     s->bulk_in_pending_start = 0;
     s->bulk_in_pending_end = 0;
     s->bulk_in_pending_num = 0;
+    s->current_bulk_in = NULL;
 }
 
 static void ccid_bulk_in_release(USBCCIDState *s)
@@ -621,26 +628,6 @@ static void *ccid_reserve_recv_buf(USBCCIDState *s, uint16_t len)
     return bulk_in->data;
 }
 
-static void ccid_reset(USBCCIDState *s)
-{
-    ccid_bulk_in_clear(s);
-    ccid_clear_pending_answers(s);
-}
-
-static void ccid_detach(USBCCIDState *s)
-{
-    ccid_reset(s);
-}
-
-static void ccid_handle_reset(USBDevice *dev)
-{
-    USBCCIDState *s = USB_CCID_DEV(dev);
-
-    DPRINTF(s, 1, "Reset\n");
-
-    ccid_reset(s);
-}
-
 static const char *ccid_control_to_str(USBCCIDState *s, int request)
 {
     switch (request) {
@@ -918,6 +905,31 @@ static void ccid_reset_parameters(USBCCIDState *s)
    s->abProtocolDataStructure = defaultProtocolDataStructure;
 }
 
+static void ccid_reset(USBCCIDState *s)
+{
+    ccid_bulk_in_clear(s);
+    ccid_clear_pending_answers(s);
+    s->bulk_out_pos = 0;
+    s->last_answer_error = 0;
+    s->notify_slot_change = false;
+    ccid_reset_error_status(s);
+    ccid_reset_parameters(s);
+}
+
+static void ccid_detach(USBCCIDState *s)
+{
+    ccid_reset(s);
+}
+
+static void ccid_handle_reset(USBDevice *dev)
+{
+    USBCCIDState *s = USB_CCID_DEV(dev);
+
+    DPRINTF(s, 1, "Reset\n");
+
+    ccid_reset(s);
+}
+
 /* NOTE: only a single slot is supported (SLOT_0) */
 static void ccid_on_slot_change(USBCCIDState *s, bool full)
 {
@@ -1349,14 +1361,6 @@ static void ccid_realize(USBDevice *dev, Error **errp)
     s->dev.speedmask = USB_SPEED_MASK_FULL;
     s->notify_slot_change = false;
     s->powered = true;
-    s->pending_answers_num = 0;
-    s->last_answer_error = 0;
-    s->bulk_in_pending_start = 0;
-    s->bulk_in_pending_end = 0;
-    s->current_bulk_in = NULL;
-    ccid_reset_error_status(s);
-    s->bulk_out_pos = 0;
-    ccid_reset_parameters(s);
     ccid_reset(s);
     s->debug = parse_debug_env("QEMU_CCID_DEBUG", D_VERBOSE, s->debug);
 }

-- 
2.55.0