[PATCH 05/27] hw/usb/dev-smartcard-reader: fix dwMaxCCIDMessageLength descriptor
Marc-André Lureau <[email protected]> Wed, 05 Aug 2026 15:50:55 +0400
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
The CCID class descriptor advertises dwMaxCCIDMessageLength = 65554
(the extended-APDU maximum), but bulk-IN storage is only 384 bytes.
Since the device operates at TPDU level, the spec minimum is just
wMaxPacketSize (64 bytes), and the actual limit is the bulk-IN buffer.
Set dwMaxCCIDMessageLength to BULK_IN_BUF_SIZE (384) so the advertised
capability matches the implementation. Guard the change behind a
machine-compat property so older machine types preserve the original
descriptor for guest reproducibility.
Fixes: 367071447ec5 ("usb-ccid: add CCID bus")
Signed-off-by: Marc-André Lureau <[email protected]>
---
hw/core/machine.c | 1 +
hw/usb/dev-smartcard-reader.c | 12 +++++++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 73b4d82b4a1d..01e50ebe05e0 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -51,6 +51,7 @@ GlobalProperty hw_compat_11_0[] = {
{ TYPE_ARM_SMMUV3, "ssidsize", "0" },
{ TYPE_ARM_SMMUV3, "oas", "44" },
{ "migration", "switchover-ack-legacy", "on" },
+ { "usb-ccid", "x-accurate-message-length", "off" },
};
const size_t hw_compat_11_0_len = G_N_ELEMENTS(hw_compat_11_0);
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 3580465df368..a14062948071 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -314,6 +314,7 @@ struct USBCCIDState {
uint8_t powered;
uint8_t notify_slot_change;
uint8_t debug;
+ bool accurate_message_length;
};
/*
@@ -326,7 +327,7 @@ struct USBCCIDState {
* 0dc3:1004 Athena Smartcard Solutions, Inc.
*/
-static const uint8_t qemu_ccid_descriptor[] = {
+static uint8_t qemu_ccid_descriptor[] = {
/* Smart Card Device Class Descriptor */
0x36, /* u8 bLength; */
0x21, /* u8 bDescriptorType; Functional */
@@ -387,7 +388,10 @@ static const uint8_t qemu_ccid_descriptor[] = {
* u32 dwMaxCCIDMessageLength; For extended APDU in
* [261 + 10 , 65544 + 10]. Otherwise the minimum is
* wMaxPacketSize of the Bulk-OUT endpoint
+ *
+ * Corrected to BULK_IN_BUF_SIZE when x-accurate-message-length
*/
+#define CCID_DESC_OFFSET_DW_MAX_MSG_LEN 44
0x12, 0x00, 0x01, 0x00,
0xFF, /*
* u8 bClassGetResponse; Significant only for CCID that
@@ -1329,6 +1333,10 @@ static void ccid_realize(USBDevice *dev, Error **errp)
{
USBCCIDState *s = USB_CCID_DEV(dev);
+ if (s->accurate_message_length) {
+ stl_le_p(&qemu_ccid_descriptor[CCID_DESC_OFFSET_DW_MAX_MSG_LEN],
+ BULK_IN_BUF_SIZE);
+ }
usb_desc_create_serial(dev);
usb_desc_init(dev);
qbus_init(&s->bus, sizeof(s->bus), TYPE_CCID_BUS, DEVICE(dev), NULL);
@@ -1445,6 +1453,8 @@ static const VMStateDescription ccid_vmstate = {
static const Property ccid_properties[] = {
DEFINE_PROP_UINT8("debug", USBCCIDState, debug, 0),
+ DEFINE_PROP_BOOL("x-accurate-message-length", USBCCIDState,
+ accurate_message_length, true),
};
static void ccid_class_initfn(ObjectClass *klass, const void *data)
--
2.55.0