d9a8c8
diff -up ccid-1.4.26/src/ccid.c.omnikey ccid-1.4.26/src/ccid.c
d9a8c8
--- ccid-1.4.26/src/ccid.c.omnikey	2017-02-24 10:04:25.742132234 +0100
d9a8c8
+++ ccid-1.4.26/src/ccid.c	2017-02-24 10:07:26.145976335 +0100
d9a8c8
@@ -55,8 +55,16 @@ int ccid_open_hack_pre(unsigned int read
d9a8c8
 {
d9a8c8
 	_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
d9a8c8
 
d9a8c8
+	ccid_descriptor->dwNonStandardFlags = 0;
d9a8c8
+
d9a8c8
 	switch (ccid_descriptor->readerID)
d9a8c8
 	{
d9a8c8
+		case CARDMAN3121:
d9a8c8
+			ccid_descriptor->dwNonStandardFlags = CCID_NON_STAND_OMK_3121_T1;
d9a8c8
+			ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
d9a8c8
+			ccid_descriptor->dwFeatures |= CCID_CLASS_TPDU;
d9a8c8
+			break;
d9a8c8
+
d9a8c8
 		case MYSMARTPAD:
d9a8c8
 			ccid_descriptor->dwMaxIFSD = 254;
d9a8c8
 			break;
d9a8c8
diff -up ccid-1.4.26/src/ccid.h.omnikey ccid-1.4.26/src/ccid.h
d9a8c8
--- ccid-1.4.26/src/ccid.h.omnikey	2017-01-07 15:50:47.000000000 +0100
d9a8c8
+++ ccid-1.4.26/src/ccid.h	2017-02-24 10:04:25.742132234 +0100
d9a8c8
@@ -137,6 +137,7 @@ typedef struct
d9a8c8
 	 */
d9a8c8
 	char zlp;
d9a8c8
 #endif
d9a8c8
+	unsigned int dwNonStandardFlags;
d9a8c8
 } _ccid_descriptor;
d9a8c8
 
d9a8c8
 /* Features from dwFeatures */
d9a8c8
@@ -153,6 +154,9 @@ typedef struct
d9a8c8
 #define CCID_CLASS_EXTENDED_APDU	0x00040000
d9a8c8
 #define CCID_CLASS_EXCHANGE_MASK	0x00070000
d9a8c8
 
d9a8c8
+/* Features from the swNonStandardFlags */
d9a8c8
+#define CCID_NON_STAND_OMK_3121_T1	0x00000001
d9a8c8
+
d9a8c8
 /* Features from bPINSupport */
d9a8c8
 #define CCID_CLASS_PIN_VERIFY		0x01
d9a8c8
 #define CCID_CLASS_PIN_MODIFY		0x02
d9a8c8
diff -up ccid-1.4.26/src/commands.c.omnikey ccid-1.4.26/src/commands.c
d9a8c8
--- ccid-1.4.26/src/commands.c.omnikey	2017-01-07 15:50:47.000000000 +0100
d9a8c8
+++ ccid-1.4.26/src/commands.c	2017-02-24 10:11:21.297778870 +0100
d9a8c8
@@ -1292,6 +1292,39 @@ RESPONSECODE CmdXfrBlock(unsigned int re
d9a8c8
 	return return_value;
d9a8c8
 } /* CmdXfrBlock */
d9a8c8
 
d9a8c8
+static RESPONSECODE omnikey_transmit_tpdu(unsigned int reader_index,
d9a8c8
+        _ccid_descriptor *ccid_descriptor, unsigned int tx_length,
d9a8c8
+        const unsigned char *tx_buffer)
d9a8c8
+{
d9a8c8
+	unsigned char cmd[11+CMD_BUF_SIZE];	 /* CCID + APDU buffer */
d9a8c8
+	status_t ret;
d9a8c8
+
d9a8c8
+	cmd[0] = 0x6B; 				/* 3121 escape */
d9a8c8
+	i2dw(tx_length+1, cmd+1); 	/* APDU length */
d9a8c8
+	cmd[5] = ccid_descriptor->bCurrentSlotIndex;	/* slot number */
d9a8c8
+	cmd[6] = (*ccid_descriptor->pbSeq)++;
d9a8c8
+	cmd[7] = 0;
d9a8c8
+	cmd[8] = 0;
d9a8c8
+	cmd[9] = 0;
d9a8c8
+	cmd[10] = 0x1A;
d9a8c8
+
d9a8c8
+	/* check that the command is not too large */
d9a8c8
+	if (tx_length > CMD_BUF_SIZE)
d9a8c8
+	{
d9a8c8
+		DEBUG_CRITICAL2("TX Length too big: %d", tx_length);
d9a8c8
+		return IFD_NOT_SUPPORTED;
d9a8c8
+	}
d9a8c8
+
d9a8c8
+	memcpy(cmd+11, tx_buffer, tx_length);
d9a8c8
+
d9a8c8
+	ret = WritePort(reader_index, 11+tx_length, cmd);
d9a8c8
+	if (STATUS_NO_SUCH_DEVICE == ret)
d9a8c8
+		return IFD_NO_SUCH_DEVICE;
d9a8c8
+	if (ret != STATUS_SUCCESS)
d9a8c8
+		return IFD_COMMUNICATION_ERROR;
d9a8c8
+
d9a8c8
+	return IFD_SUCCESS;
d9a8c8
+} /* omnikey_transmit_tpdu */
d9a8c8
 
d9a8c8
 /*****************************************************************************
d9a8c8
  *
d9a8c8
@@ -1348,6 +1381,13 @@ RESPONSECODE CCID_Transmit(unsigned int
d9a8c8
 	}
d9a8c8
 #endif
d9a8c8
 
d9a8c8
+	/* hack for Onmikey 3121 */
d9a8c8
+	if ((ccid_descriptor->dwNonStandardFlags & CCID_NON_STAND_OMK_3121_T1) &&
d9a8c8
+		(ccid_descriptor->cardProtocol == SCARD_PROTOCOL_T1)) {
d9a8c8
+		return omnikey_transmit_tpdu(reader_index, ccid_descriptor, tx_length, 
d9a8c8
+				tx_buffer);
d9a8c8
+	}
d9a8c8
+
d9a8c8
 	cmd[0] = 0x6F; /* XfrBlock */
d9a8c8
 	i2dw(tx_length, cmd+1);	/* APDU length */
d9a8c8
 	cmd[5] = ccid_descriptor->bCurrentSlotIndex;	/* slot number */
d9a8c8
@@ -1373,8 +1413,9 @@ RESPONSECODE CCID_Transmit(unsigned int
d9a8c8
 RESPONSECODE CCID_Receive(unsigned int reader_index, unsigned int *rx_length,
d9a8c8
 	unsigned char rx_buffer[], unsigned char *chain_parameter)
d9a8c8
 {
d9a8c8
-	unsigned char cmd[10+CMD_BUF_SIZE];	/* CCID + APDU buffer */
d9a8c8
+	unsigned char cmd[11+CMD_BUF_SIZE];	/* CCID + APDU buffer */
d9a8c8
 	unsigned int length;
d9a8c8
+	unsigned char *rx_ptr = cmd+10;
d9a8c8
 	RESPONSECODE return_value = IFD_SUCCESS;
d9a8c8
 	status_t ret;
d9a8c8
 	_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
d9a8c8
@@ -1565,6 +1606,14 @@ time_request:
d9a8c8
 	}
d9a8c8
 
d9a8c8
 	length = dw2i(cmd, 1);
d9a8c8
+
d9a8c8
+	if (length && 
d9a8c8
+	  (ccid_descriptor->dwNonStandardFlags & CCID_NON_STAND_OMK_3121_T1) &&
d9a8c8
+	  (ccid_descriptor->cardProtocol == SCARD_PROTOCOL_T1)) {
d9a8c8
+		length--;
d9a8c8
+		rx_ptr = cmd+11;
d9a8c8
+	}
d9a8c8
+
d9a8c8
 	if (length <= *rx_length)
d9a8c8
 		*rx_length = length;
d9a8c8
 	else
d9a8c8
@@ -1581,7 +1630,7 @@ time_request:
d9a8c8
 	}
d9a8c8
 	else
d9a8c8
		if (length)
d9a8c8
-			memcpy(rx_buffer, cmd+10, length);
d9a8c8
+			memcpy(rx_buffer, rx_ptr, length);
d9a8c8
 
d9a8c8
 	/* Extended case?
d9a8c8
 	 * Only valid for RDR_to_PC_DataBlock frames */