[Pcsclite-cvs-commit] r2094 - trunk/Drivers/ccid/src

Ludovic Rousseau rousseau at costa.debian.org
Mon Jul 3 14:21:15 UTC 2006


Author: rousseau
Date: 2006-07-03 14:21:15 +0000 (Mon, 03 Jul 2006)
New Revision: 2094

Modified:
   trunk/Drivers/ccid/src/commands.c
Log:
add CmdXfrBlockAPDU_extended() to support Extended APDU readers


Modified: trunk/Drivers/ccid/src/commands.c
===================================================================
--- trunk/Drivers/ccid/src/commands.c	2006-07-03 14:03:58 UTC (rev 2093)
+++ trunk/Drivers/ccid/src/commands.c	2006-07-03 14:21:15 UTC (rev 2094)
@@ -43,6 +43,10 @@
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 
 /* internal functions */
+static RESPONSECODE CmdXfrBlockAPDU_extended(unsigned int reader_index,
+	unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
+	unsigned char rx_buffer[]);
+
 static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
 	unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
 	unsigned char rx_buffer[]);
@@ -870,6 +874,126 @@
 
 /*****************************************************************************
  *
+ *					CmdXfrBlockAPDU_extended
+ *
+ ****************************************************************************/
+static RESPONSECODE CmdXfrBlockAPDU_extended(unsigned int reader_index,
+	unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
+	unsigned char rx_buffer[])
+{
+	RESPONSECODE return_value;
+	_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
+	unsigned char chain_parameter;
+	unsigned int local_tx_length, sent_length;
+	unsigned int local_rx_length, received_length;
+
+	DEBUG_COMM2("T=0 (extended): %d bytes", tx_length);
+
+	/* send the APDU */
+	sent_length = 0;
+
+	/* we suppose one command is enough */
+	chain_parameter = 0x00;
+
+	local_tx_length = tx_length - sent_length;
+	if (local_tx_length > CMD_BUF_SIZE)
+	{
+		local_tx_length = CMD_BUF_SIZE;
+		/* the command APDU begins with this command, and continue in the next
+		 * PC_to_RDR_XfrBlock */
+		chain_parameter = 0x01;
+	}
+	if (local_tx_length > ccid_descriptor->dwMaxCCIDMessageLength-10)
+	{
+		local_tx_length = ccid_descriptor->dwMaxCCIDMessageLength-10;
+		chain_parameter = 0x01;
+	}
+
+send_next_block:
+	return_value = CCID_Transmit(reader_index, local_tx_length, tx_buffer,
+		chain_parameter, 0);
+	if (return_value != IFD_SUCCESS)
+		return return_value;
+
+	sent_length += local_tx_length;
+	tx_buffer += local_tx_length;
+
+	/* we just sent the last block (0x02) or only one block was needded (0x00) */
+	if ((0x02 == chain_parameter) || (0x00 == chain_parameter))
+		goto receive_block;
+
+	/* read a nul block */
+	return_value = CCID_Receive(reader_index, &local_rx_length, NULL, NULL);
+	if (return_value != IFD_SUCCESS)
+		return return_value;
+
+	/* size of the next block */
+	if (tx_length - sent_length > local_tx_length)
+	{
+		/* the abData field continues a command APDU and
+		 * another block is to follow */
+		chain_parameter = 0x03;
+	}
+	else
+	{
+		/* this abData field continues a command APDU and ends
+		 * the APDU command */
+		chain_parameter = 0x02;
+
+		/* last (smaller) block */
+		local_tx_length = tx_length - sent_length;
+	}
+
+	goto send_next_block;
+
+receive_block:
+	/* receive the APDU */
+	received_length = 0;
+
+receive_next_block:
+	local_rx_length = *rx_length - received_length;
+	return_value = CCID_Receive(reader_index, &local_rx_length, rx_buffer,
+		&chain_parameter);
+	if (return_value != IFD_SUCCESS)
+		return return_value;
+
+	/* advance in the reiceiving buffer */
+	rx_buffer += local_rx_length;
+	received_length += local_rx_length;
+
+	switch (chain_parameter)
+	{
+		/* the response APDU begins and ends in this command */
+		case 0x00:
+		/* this abData field continues the response APDU and ends the response
+		 * APDU */
+		case 0x02:
+			break;
+
+		/* the response APDU begins with this command and is to continue */
+		case 0x01:
+		/* this abData field continues the response APDU and another block is
+		 * to follow */
+		case 0x03:
+		/* empty abData field, continuation of the command APDU is expected in
+		 * next PC_to_RDR_XfrBlock command */
+		case 0x10:
+			/* send a nul block */
+			return_value = CCID_Transmit(reader_index, 0, NULL, 0, 0);
+			if (return_value != IFD_SUCCESS)
+				return return_value;
+
+			goto receive_next_block;
+	}
+
+	*rx_length = received_length;
+
+	return IFD_SUCCESS;
+} /* CmdXfrBlockTPDU_T0_extended */
+
+
+/*****************************************************************************
+ *
  *					CmdXfrBlockTPDU_T0
  *
  ****************************************************************************/




More information about the Pcsclite-cvs-commit mailing list