|
@@ -1001,8 +1001,7 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
|
|
CCID_Header *ccid_header;
|
|
CCID_Header *ccid_header;
|
|
|
|
|
|
if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
|
|
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;
|
|
ccid_header = (CCID_Header *)s->bulk_out_data;
|
|
usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
|
|
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,
|
|
DPRINTF(s, 1,
|
|
"%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
|
|
"%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
|
|
__func__);
|
|
__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);
|
|
((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",
|
|
"handle_data: ERROR: unhandled message type %Xh\n",
|
|
ccid_header->bMessageType);
|
|
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;
|
|
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)
|
|
static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
|