From 1f2721a493a53bc712cd9d8429fb24a81da21874 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 16 Sep 2010 11:03:14 +0900 Subject: [PATCH] Fixed handling of USB CCID/ICCD error --- ChangeLog | 6 +++++ THANKS | 2 +- src/usb-icc.c | 71 ++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 66 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5a8fe53..7858222 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-09-16 NIIBE Yutaka + + * src/usb-icc.c (icc_error): New function. + (icc_handle_data): Call icc_error. + Don't go to STATE_START on errors. + 2010-09-13 NIIBE Yutaka * Version 0.2. diff --git a/THANKS b/THANKS index 5c60646..6c7b619 100644 --- a/THANKS +++ b/THANKS @@ -6,7 +6,7 @@ encouraging the development, testing the implementation, suggesting improvements, or fixing bugs. Here is a list of those people. Jan Sur jan@suhr.info -NAGAMI Takeshi nagami-takeshi@aist.go.jp Kaz Kojima kkojima@rr.iij4u.or.jp +NAGAMI Takeshi nagami-takeshi@aist.go.jp Shane Coughlan scoughlan@openinventionnetwork.com Werner Koch wk@gnupg.org diff --git a/src/usb-icc.c b/src/usb-icc.c index bafa0ef..ab04304 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -57,6 +57,12 @@ #define ICC_ERROR_XFR_OVERRUN 0xFC +/* + * Since command-byte is at offset 0, + * error with offset 0 means "command not supported". + */ +#define ICC_OFFSET_CMD_NOT_SUPPORTED 0 +#define ICC_OFFSET_PARAM 8 struct icc_header { uint8_t msg_type; @@ -175,6 +181,41 @@ static const char ATR[] = { (0x94^0x11^0x81^0x31^0xFE^0x55^'F'^'S'^'I'^'J') }; +/* + * Send back error + */ +void +icc_error (int offset) +{ + icc_tx_data[0] = ICC_SLOT_STATUS_RET; /* Any value should be OK */ + icc_tx_data[1] = 0x00; + icc_tx_data[2] = 0x00; + icc_tx_data[3] = 0x00; + icc_tx_data[4] = 0x00; + icc_tx_data[5] = 0x00; /* Slot */ + icc_tx_data[ICC_MSG_SEQ_OFFSET] = icc_seq; + if (icc_state == ICC_STATE_START) + /* 1: ICC present but not activated 2: No ICC present */ + icc_tx_data[ICC_MSG_STATUS_OFFSET] = 1; + else + /* An ICC is present and active */ + icc_tx_data[ICC_MSG_STATUS_OFFSET] = 0; + icc_tx_data[ICC_MSG_STATUS_OFFSET] |= ICC_CMD_STATUS_ERROR; /* Failed */ + icc_tx_data[ICC_MSG_ERROR_OFFSET] = offset; + icc_tx_data[ICC_MSG_CHAIN_OFFSET] = 0x00; + + if (!icc_tx_ready ()) + { + DEBUG_INFO ("ERR0D\r\n"); + } + else + { + icc_tx_size = ICC_MSG_HEADER_SIZE; + USB_SIL_Write (EP1_IN, icc_tx_data, icc_tx_size); + SetEPTxValid (ENDP1); + } +} + /* Send back ATR (Answer To Reset) */ enum icc_state icc_power_on (void) @@ -334,8 +375,9 @@ icc_handle_data (void) else if (icc_header->msg_type == ICC_SLOT_STATUS) icc_send_status (); else - { /* XXX: error */ + { DEBUG_INFO ("ERR01\r\n"); + icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); } break; case ICC_STATE_WAIT: @@ -367,17 +409,18 @@ icc_handle_data (void) next_state = ICC_STATE_RECEIVE; } else - { /* XXX: error */; + { DEBUG_INFO ("ERR02\r\n"); + icc_error (ICC_OFFSET_PARAM); } } else if (icc_header->msg_type == ICC_SET_PARAMS) icc_send_params (); else - { /* XXX: error */ + { DEBUG_INFO ("ERR03\r\n"); DEBUG_BYTE (icc_header->msg_type); - next_state = ICC_STATE_START; + icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); } break; case ICC_STATE_EXECUTE: @@ -389,10 +432,10 @@ icc_handle_data (void) else if (icc_header->msg_type == ICC_SLOT_STATUS) icc_send_status (); else - { /* XXX: error */ + { DEBUG_INFO ("ERR04\r\n"); DEBUG_BYTE (icc_header->msg_type); - next_state = ICC_STATE_START; + icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); } break; case ICC_STATE_RECEIVE: @@ -418,8 +461,9 @@ icc_handle_data (void) else if (icc_header->param == 3) icc_send_data_block (0, 0, 0x10, NULL, 0); else - { /* XXX: error */ + { DEBUG_INFO ("ERR08\r\n"); + icc_error (ICC_OFFSET_PARAM); } } else /* Overrun */ @@ -430,10 +474,11 @@ icc_handle_data (void) } } else - { /* XXX: error */ + { DEBUG_INFO ("ERR05\r\n"); DEBUG_BYTE (icc_header->msg_type); - next_state = ICC_STATE_START; + icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); + next_state = ICC_STATE_WAIT; } break; case ICC_STATE_SEND: @@ -459,18 +504,20 @@ icc_handle_data (void) } } else - { /* XXX: error */ + { DEBUG_INFO ("ERR0A\r\n"); DEBUG_BYTE (icc_header->param >> 8); DEBUG_BYTE (icc_header->param & 0xff); + icc_error (ICC_OFFSET_PARAM); next_state = ICC_STATE_WAIT; } } else - { /* XXX: error */ + { DEBUG_INFO ("ERR06\r\n"); DEBUG_BYTE (icc_header->msg_type); - next_state = ICC_STATE_START; + icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); + next_state = ICC_STATE_WAIT; } break; }