aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/usb/dev-smartcard-reader.c116
1 files changed, 61 insertions, 55 deletions
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 1325ea1659..badcfcbf7d 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1001,8 +1001,7 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
CCID_Header *ccid_header;
if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
- p->status = USB_RET_STALL;
- return;
+ goto err;
}
ccid_header = (CCID_Header *)s->bulk_out_data;
usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
@@ -1017,64 +1016,71 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
DPRINTF(s, 1,
"%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
__func__);
- } else {
- DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__,
- ccid_header->bMessageType,
- ccid_message_type_to_str(ccid_header->bMessageType));
- switch (ccid_header->bMessageType) {
- case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
- ccid_write_slot_status(s, ccid_header);
- break;
- case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
- DPRINTF(s, 1, "%s: PowerOn: %d\n", __func__,
+ goto err;
+ }
+
+ DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__,
+ ccid_header->bMessageType,
+ ccid_message_type_to_str(ccid_header->bMessageType));
+ switch (ccid_header->bMessageType) {
+ case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
+ ccid_write_slot_status(s, ccid_header);
+ break;
+ case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
+ DPRINTF(s, 1, "%s: PowerOn: %d\n", __func__,
((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
- s->powered = true;
- if (!ccid_card_inserted(s)) {
- ccid_report_error_failed(s, ERROR_ICC_MUTE);
- }
- /* atr is written regardless of error. */
- ccid_write_data_block_atr(s, ccid_header);
- break;
- case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
- ccid_reset_error_status(s);
- s->powered = false;
- ccid_write_slot_status(s, ccid_header);
- break;
- case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
- ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
- break;
- case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
- ccid_reset_error_status(s);
- ccid_set_parameters(s, ccid_header);
- ccid_write_parameters(s, ccid_header);
- break;
- case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
- ccid_reset_error_status(s);
- ccid_reset_parameters(s);
- ccid_write_parameters(s, ccid_header);
- break;
- case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
- ccid_reset_error_status(s);
- ccid_write_parameters(s, ccid_header);
- break;
- case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical:
- ccid_report_error_failed(s, 0);
- ccid_write_slot_status(s, ccid_header);
- break;
- default:
- DPRINTF(s, 1,
+ s->powered = true;
+ if (!ccid_card_inserted(s)) {
+ ccid_report_error_failed(s, ERROR_ICC_MUTE);
+ }
+ /* atr is written regardless of error. */
+ ccid_write_data_block_atr(s, ccid_header);
+ break;
+ case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
+ ccid_reset_error_status(s);
+ s->powered = false;
+ ccid_write_slot_status(s, ccid_header);
+ break;
+ case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
+ ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
+ break;
+ case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
+ ccid_reset_error_status(s);
+ ccid_set_parameters(s, ccid_header);
+ ccid_write_parameters(s, ccid_header);
+ break;
+ case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
+ ccid_reset_error_status(s);
+ ccid_reset_parameters(s);
+ ccid_write_parameters(s, ccid_header);
+ break;
+ case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
+ ccid_reset_error_status(s);
+ ccid_write_parameters(s, ccid_header);
+ break;
+ case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical:
+ ccid_report_error_failed(s, 0);
+ ccid_write_slot_status(s, ccid_header);
+ break;
+ default:
+ DPRINTF(s, 1,
"handle_data: ERROR: unhandled message type %Xh\n",
ccid_header->bMessageType);
- /*
- * The caller is expecting the device to respond, tell it we
- * don't support the operation.
- */
- ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
- ccid_write_slot_status(s, ccid_header);
- break;
- }
+ /*
+ * The caller is expecting the device to respond, tell it we
+ * don't support the operation.
+ */
+ ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
+ ccid_write_slot_status(s, ccid_header);
+ break;
}
s->bulk_out_pos = 0;
+ return;
+
+err:
+ p->status = USB_RET_STALL;
+ s->bulk_out_pos = 0;
+ return;
}
static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)