diff -up ./src/ccid.c.omnikey ./src/ccid.c --- ./src/ccid.c.omnikey 2012-06-08 07:17:11.000000000 -0700 +++ ./src/ccid.c 2014-09-26 16:40:54.279531436 -0700 @@ -47,8 +47,13 @@ int ccid_open_hack_pre(unsigned int read { _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); + ccid_descriptor->dwNonStandardFlags = 0; + switch (ccid_descriptor->readerID) { + case CARDMAN3121: + ccid_descriptor->dwNonStandardFlags = CCID_NON_STAND_OMK_3121_T1; + /* fall through */ case CARDMAN3121+1: /* Reader announces APDU but is in fact TPDU */ ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK; diff -up ./src/ccid.h.omnikey ./src/ccid.h --- ./src/ccid.h.omnikey 2012-06-08 07:17:11.000000000 -0700 +++ ./src/ccid.h 2014-09-26 16:40:54.279531436 -0700 @@ -141,6 +141,7 @@ typedef struct * Gemalto extra features, if any */ struct GEMALTO_FIRMWARE_FEATURES *gemalto_firmware_features; + unsigned int dwNonStandardFlags; } _ccid_descriptor; /* Features from dwFeatures */ @@ -156,6 +157,9 @@ typedef struct #define CCID_CLASS_EXTENDED_APDU 0x00040000 #define CCID_CLASS_EXCHANGE_MASK 0x00070000 +/* Features from the swNonStandardFlags */ +#define CCID_NON_STAND_OMK_3121_T1 0x00000001 + /* Features from bPINSupport */ #define CCID_CLASS_PIN_VERIFY 0x01 #define CCID_CLASS_PIN_MODIFY 0x02 diff -up ./src/commands.c.omnikey ./src/commands.c --- ./src/commands.c.omnikey 2014-09-26 16:40:54.276531385 -0700 +++ ./src/commands.c 2014-09-26 16:41:39.463293364 -0700 @@ -1186,6 +1186,39 @@ RESPONSECODE CmdXfrBlock(unsigned int re return return_value; } /* CmdXfrBlock */ +static RESPONSECODE omnikey_transmit_tpdu(unsigned int reader_index, + _ccid_descriptor *ccid_descriptor, unsigned int tx_length, + const unsigned char *tx_buffer) +{ + unsigned char cmd[11+CMD_BUF_SIZE]; /* CCID + APDU buffer */ + status_t ret; + + cmd[0] = 0x6B; /* 3121 escape */ + i2dw(tx_length+1, cmd+1); /* APDU length */ + cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ + cmd[6] = (*ccid_descriptor->pbSeq)++; + cmd[7] = 0; + cmd[8] = 0; + cmd[9] = 0; + cmd[10] = 0x1A; + + /* check that the command is not too large */ + if (tx_length > CMD_BUF_SIZE) + { + DEBUG_CRITICAL2("TX Length too big: %d", tx_length); + return IFD_NOT_SUPPORTED; + } + + memcpy(cmd+11, tx_buffer, tx_length); + + ret = WritePort(reader_index, 11+tx_length, cmd); + if (STATUS_NO_SUCH_DEVICE == ret) + return IFD_NO_SUCH_DEVICE; + if (ret != STATUS_SUCCESS) + return IFD_COMMUNICATION_ERROR; + + return IFD_SUCCESS; +} /* omnikey_transmit_tpdu */ /***************************************************************************** * @@ -1242,6 +1275,13 @@ RESPONSECODE CCID_Transmit(unsigned int } #endif + /* hack for Onmikey 3121 */ + if ((ccid_descriptor->dwNonStandardFlags & CCID_NON_STAND_OMK_3121_T1) && + (ccid_descriptor->cardProtocol == SCARD_PROTOCOL_T1)) { + return omnikey_transmit_tpdu(reader_index, ccid_descriptor, tx_length, + tx_buffer); + } + cmd[0] = 0x6F; /* XfrBlock */ i2dw(tx_length, cmd+1); /* APDU length */ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ @@ -1267,13 +1307,14 @@ RESPONSECODE CCID_Transmit(unsigned int RESPONSECODE CCID_Receive(unsigned int reader_index, unsigned int *rx_length, unsigned char rx_buffer[], unsigned char *chain_parameter) { - unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */ + unsigned char cmd[11+CMD_BUF_SIZE]; /* CCID + APDU buffer */ unsigned int length; + unsigned char *rx_ptr = cmd+10; RESPONSECODE return_value = IFD_SUCCESS; status_t ret; + _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); #ifndef TWIN_SERIAL - _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); if (PROTOCOL_ICCD_A == ccid_descriptor->bInterfaceProtocol) { @@ -1447,6 +1488,14 @@ time_request: } length = dw2i(cmd, 1); + + if (length && + (ccid_descriptor->dwNonStandardFlags & CCID_NON_STAND_OMK_3121_T1) && + (ccid_descriptor->cardProtocol == SCARD_PROTOCOL_T1)) { + length--; + rx_ptr = cmd+11; + } + if (length <= *rx_length) *rx_length = length; else @@ -1463,7 +1512,7 @@ time_request: return_value = IFD_COMMUNICATION_ERROR; } else - memcpy(rx_buffer, cmd+10, length); + memcpy(rx_buffer, rx_ptr, length); /* Extended case? * Only valid for RDR_to_PC_DataBlock frames */