[PATCH 25/27] hw/usb/dev-smartcard-reader: advertise T=1 protocol support
Marc-André Lureau <[email protected]> Wed, 05 Aug 2026 15:51:15 +0400
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
The CCID descriptor only advertised T=0, but it actually handles t=1 since it shuttles framed blocks to the backend. libcacard advertized T=0 in the ATR, so it works fine. This allows passthrough cards to work at t=1 if they need to. Add a configurable property to also advertise T=1 in the dwProtocols field, enabled by default. Use the correct error code (7, ICC protocol not supported) instead of CMD_NOT_SUPPORTED when SetParameters receives an invalid protocol. Note: I only tested with libcacard emulation. Signed-off-by: Marc-André Lureau <[email protected]> --- hw/core/machine.c | 1 + hw/usb/dev-smartcard-reader.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 790d947e28d1..e9fecdec18df 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -53,6 +53,7 @@ GlobalProperty hw_compat_11_0[] = { { "migration", "switchover-ack-legacy", "on" }, { "usb-ccid", "x-accurate-message-length", "off" }, { "usb-ccid", "x-pin-support", "on" }, + { "usb-ccid", "x-t1-support", "off" }, { "usb-ccid", "x-migrate-pending-answers", "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 8520a2dab216..99086befe0b8 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -169,6 +169,7 @@ enum { ERROR_CMD_SLOT_BUSY = -32, ERROR_BAD_DWLENGTH = 1, ERROR_SLOT_NOT_EXIST = 5, + ERROR_PROTOCOL_INVALID = 7, }; /* 6.2.6 RDR_to_PC_SlotStatus definitions */ @@ -330,6 +331,7 @@ struct USBCCIDState { bool migrate_pending_answers; bool pending_answers_loaded; bool pin_support; + bool t1_support; }; static uint32_t ccid_bulk_in_pending_num(USBCCIDState *s) @@ -368,6 +370,7 @@ static uint8_t qemu_ccid_descriptor[] = { */ 0x07, /* u8 bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */ +#define CCID_DESC_OFFSET_DW_PROTOCOLS 0x06 0x01, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/ 0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */ /* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */ @@ -968,7 +971,7 @@ static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv) uint32_t protocol_num = ph->bProtocolNum & 3; if (protocol_num != 0 && protocol_num != 1) { - ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED); + ccid_report_error_failed(s, ERROR_PROTOCOL_INVALID); return; } s->bProtocolNum = protocol_num; @@ -1546,6 +1549,9 @@ static void ccid_realize(USBDevice *dev, Error **errp) if (!s->pin_support) { qemu_ccid_descriptor[CCID_DESC_OFFSET_B_PIN_SUPPORT] = 0; } + if (s->t1_support) { + qemu_ccid_descriptor[CCID_DESC_OFFSET_DW_PROTOCOLS] |= 0x2; + } usb_desc_create_serial(dev); usb_desc_init(dev); qbus_init(&s->bus, sizeof(s->bus), TYPE_CCID_BUS, DEVICE(dev), NULL); @@ -1742,6 +1748,8 @@ static const Property ccid_properties[] = { accurate_message_length, true), DEFINE_PROP_BOOL("x-pin-support", USBCCIDState, pin_support, false), + DEFINE_PROP_BOOL("x-t1-support", USBCCIDState, + t1_support, true), DEFINE_PROP_BOOL("x-migrate-pending-answers", USBCCIDState, migrate_pending_answers, true), }; -- 2.55.0