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 */