[Pcsclite-cvs-commit] HandlerTest/Host handler_test.c,1.3,1.4

rousseau@quantz.debian.org rousseau@quantz.debian.org
Wed, 29 Oct 2003 22:30:35 +0100


Update of /cvsroot/pcsclite/HandlerTest/Host
In directory quantz:/tmp/cvs-serv29995

Modified Files:
	handler_test.c 
Log Message:
a lot of new options. See -h for details.


Index: handler_test.c
===================================================================
RCS file: /cvsroot/pcsclite/HandlerTest/Host/handler_test.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- handler_test.c	4 Sep 2003 13:16:36 -0000	1.3
+++ handler_test.c	29 Oct 2003 21:30:33 -0000	1.4
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <dlfcn.h>
 #include <stdlib.h>
+#include <getopt.h>
 
 #include "ifdhandler.h"
 #include "debug.h"
@@ -34,6 +35,11 @@
 #define LUN 0
 #define ENV_LIBNAME "LIB"
 
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
 int handler_test(int lun, int channel);
 void pcsc_error(int rv);
 int exchange(char *text, DWORD lun, SCARD_IO_HEADER SendPci,
@@ -73,43 +79,115 @@
 
 struct f_t f = { NULL, NULL, NULL, NULL, NULL };
 
+#define CASE1 (1)
+#define CASE2 (1<<1)
+#define CASE3 (1<<2)
+#define CASE4 (1<<3)
+
+/* flags */
+char full = FALSE;
+int timerequest = -1;
+char cases = 0;
+char tpdu = FALSE;
+char apdu = FALSE;
+
+/* getopt(3) */
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+
+void help(char *argv0)
+{
+	printf("\nUsage: %s [-f] [-t val] [-1] [-2] [-3] [-4] [-A] [-T] libname [channel]\n", argv0);
+	printf("  -f : test APDU with every possible lengths\n");
+	printf("  -t val : use val as timerequest value. Set to 0 to avoid test\n");
+	printf("  -1 : test CASE 1 APDU\n");
+	printf("  -2 : test CASE 2 APDU\n");
+	printf("  -3 : test CASE 3 APDU\n");
+	printf("  -4 : test CASE 4 APDU\n");
+	printf("  -A : use APDU\n");
+	printf("  -T : use TPDU\n");
+	printf("  libname : driver to load\n");
+	printf("  channel : channel to use (for a serial driver)\n\n");
+	printf("example: %s /usr/lib/pcsc/drivers/serial/libGemPC410.so 2\n",
+		argv0);
+	printf(" to load the libGemPC410 and use /dev/pcsc/2\n");
+	printf("or define environment variable LIB\n");
+	printf(" LIB=/usr/lib/pcsc/drivers/serial/libGemPC410.so %s\n", argv0);
+
+	exit(1);
+} /* help */
+
 int main(int argc, char *argv[])
 {
 	void *lib_handle = NULL;
 	int ret;
 	int channel = 0;
 	char *driver;
+	int opt;
+
+	while ((opt = getopt(argc, argv, "ft:1234AT")) != EOF)
+	{
+		switch (opt)
+		{
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+				cases |= 1 << (opt - '1');
+				printf("test case: %c\n", opt);
+				break;
+
+			case 'f':
+				full = TRUE;
+				printf("Full test (all APDU sizes)\n");
+				break;
+
+			case 't':
+				timerequest = atol(optarg);
+				printf("time request: %d\n", timerequest);
+				break;
+
+			case 'A':
+				apdu = TRUE;
+				printf("Use APDU\n");
+				break;
+
+			case 'T':
+				tpdu = TRUE;
+				printf("Use TPDU\n");
+				break;
+
+			default:
+				printf ("caractère: %c (0x%02X)\n", opt, opt);
+				help(argv[0]);
+		}
+	}
 
 	driver = getenv(ENV_LIBNAME);
 
 	if (driver == NULL)
 	{
-		if (!(argc == 2 || argc == 3))
-		{
-			printf("Usage: %s libname [channel]\n", argv[0]);
-			printf("example: %s /usr/lib/pcsc/drivers/serial/libGemPC410.so 2\n",
-				argv[0]);
-			printf(" to load the libGemPC410 and use /dev/pcsc/2\n");
-			printf("or define environment variable LIB\n");
-			printf(" LIB=/usr/lib/pcsc/drivers/serial/libGemPC410.so %s\n",
-				argv[0]);
-			return 1;
-		}
+		if (argc - optind < 1)
+			help(argv[0]);
 
 		// driver
-		driver = argv[1];
+		driver = argv[optind];
 
 		// channel
-		if (argc == 3)
-			channel = atoi(argv[2]);
+		if (argc - optind >= 2)
+			channel = atoi(argv[optind+1]);
 	}
 	else
 	{
 		// channel
-		if (argc == 2)
-			channel = atoi(argv[1]);
+		if (argc - optind > 1)
+			channel = atoi(argv[optind]);
 	}
 
+	printf("Using driver: %s\n", driver);
+	printf("Using channel: %d\n", channel);
+
 	lib_handle = dlopen(driver, RTLD_LAZY);
 	if (lib_handle == NULL)
 	{
@@ -141,6 +219,7 @@
 	int e_length;	// expected result length
 	char *text = NULL;
 	int time;
+	int start, end;
 
 	rv = f.IFDHCreateChannel(lun, channel);
 
@@ -197,232 +276,359 @@
 		goto end;
 
 	/* Time Request */
-	text = "Time Request";
-	time = 10;
-
-	s[0] = 0x80;
-	s[1] = 0x25;
-	s[2] = 0x00;
-	s[3] = time;
-
-	dwSendLength = 4;
-	dwRecvLength = sizeof(r);
+	if (timerequest >= 0)
+	{
+		text = "Time Request";
+		time = timerequest;
 
-	e[0] = 0x90;
-	e[1] = 0x00;
-	e_length = 2;
+		s[0] = 0x80;
+		s[1] = 0x38;
+		s[2] = 0x00;
+		s[3] = time;
 
-	if (exchange(text, lun, SendPci, &RecvPci,
-		s, dwSendLength, r, &dwRecvLength, e, e_length))
-		goto end;
+		dwSendLength = 4;
+		dwRecvLength = sizeof(r);
 
-	/* Case 1, APDU */
-	text = "Case 1, APDU: CLA INS P1 P2, L(Cmd) = 4";
-	s[0] = 0x80;
-	s[1] = 0x21;
-	s[2] = 0x00;
-	s[3] = 0x00;
+		e[0] = 0x90;
+		e[1] = 0x00;
+		e_length = 2;
 
-	dwSendLength = 4;
-	dwRecvLength = sizeof(r);
+		if (exchange(text, lun, SendPci, &RecvPci,
+			s, dwSendLength, r, &dwRecvLength, e, e_length))
+			goto end;
+	}
 
-	e[0] = 0x90;
-	e[1] = 0x00;
-	e_length = 2;
+	if (cases & CASE1)
+	{
+		/* Case 1, APDU */
+		text = "Case 1, APDU: CLA INS P1 P2, L(Cmd) = 4";
+		s[0] = 0x80;
+		s[1] = 0x30;
+		s[2] = 0x00;
+		s[3] = 0x00;
 
-	if (exchange(text, lun, SendPci, &RecvPci,
-		s, dwSendLength, r, &dwRecvLength, e, e_length))
-		goto end;
+		dwSendLength = 4;
+		dwRecvLength = sizeof(r);
 
-	/* Case 1, TPDU */
-	text = "Case 1, TPDU: CLA INS P1 P2 P3 (=0), L(Cmd) = 5";
-	s[0] = 0x80;
-	s[1] = 0x21;
-	s[2] = 0x00;
-	s[3] = 0x00;
-	s[4] = 0x00;
+		e[0] = 0x90;
+		e[1] = 0x00;
+		e_length = 2;
 
-	dwSendLength = 5;
-	dwRecvLength = sizeof(r);
+		if (exchange(text, lun, SendPci, &RecvPci,
+			s, dwSendLength, r, &dwRecvLength, e, e_length))
+			goto end;
 
-	e[0] = 0x90;
-	e[1] = 0x00;
-	e_length = 2;
+		/* Case 1, TPDU */
+		text = "Case 1, TPDU: CLA INS P1 P2 P3 (=0), L(Cmd) = 5";
+		s[0] = 0x80;
+		s[1] = 0x30;
+		s[2] = 0x00;
+		s[3] = 0x00;
+		s[4] = 0x00;
 
-	if (exchange(text, lun, SendPci, &RecvPci,
-		s, dwSendLength, r, &dwRecvLength, e, e_length))
-		goto end;
+		dwSendLength = 5;
+		dwRecvLength = sizeof(r);
 
-	/* Case 2 */
-	/*
-	 * 248 (0xF8) is max size for one USB or GBP paquet
-	 * 255 (0xFF) maximum, 1 minimum
-	 */
-	text = "Case 2: CLA INS P1 P2 Le, L(Cmd) = 5";
-	len_i = 255;
+		e[0] = 0x90;
+		e[1] = 0x00;
+		e_length = 2;
 
-	s[0] = 0x80;
-	s[1] = 0x22;
-	s[2] = 0x00;
-	s[3] = 0x00;
-	s[4] = len_i;
+		if (exchange(text, lun, SendPci, &RecvPci,
+			s, dwSendLength, r, &dwRecvLength, e, e_length))
+			goto end;
+	}
 
-	for (i=0; i<len_i; i++)
-		s[5+i] = i;
+	if (cases & CASE2)
+	{
+		/* Case 2 */
+		/*
+		 * 248 (0xF8) is max size for one USB or GBP paquet
+		 * 255 (0xFF) maximum, 1 minimum
+		 */
+		text = "Case 2: CLA INS P1 P2 Le, L(Cmd) = 5";
+		start = end = 255;
+		if (full)
+			start = 1;
 
-	dwSendLength = len_i + 5;
-	dwRecvLength = sizeof(r);
+		for (len_i = start; len_i <= end; len_i++)
+		{
+			s[0] = 0x80;
+			s[1] = 0x32;
+			s[2] = 0x00;
+			s[3] = 0x00;
+			s[4] = len_i;
 
-	e[0] = 0x90;
-	e[1] = 0x00;
-	e_length = 2;
+			for (i=0; i<len_i; i++)
+				s[5+i] = i;
 
-	if (exchange(text, lun, SendPci, &RecvPci,
-		s, dwSendLength, r, &dwRecvLength, e, e_length))
-		goto end;
+			dwSendLength = len_i + 5;
+			dwRecvLength = sizeof(r);
 
-	/* Case 3 */
-	/*
-	 * 252  (0xFC) is max size for one USB or GBP paquet
-	 * 256 (0x100) maximum, 1 minimum
-	 */
-	text = "Case 3: CLA INS P1 P2 Lc Data, L(Cmd) = 5 + Lc";
-	len_o = 256;
+			e[0] = 0x90;
+			e[1] = 0x00;
+			e_length = 2;
 
-	s[0] = 0x80;
-	s[1] = 0x23;
-	if (len_o > 255)
-	{
-		s[2] = 0x01;
-		s[3] = len_o-256;
+			if (exchange(text, lun, SendPci, &RecvPci,
+				s, dwSendLength, r, &dwRecvLength, e, e_length))
+				goto end;
+		}
 	}
-	else
+
+	if (cases & CASE3)
 	{
-		s[2] = 0x00;
-		s[3] = len_o;
-	}
-	s[4] = len_o;
+		/* Case 3 */
+		/*
+		 * 252  (0xFC) is max size for one USB or GBP paquet
+		 * 256 (0x100) maximum, 1 minimum
+		 */
+		text = "Case 3: CLA INS P1 P2 Lc Data, L(Cmd) = 5 + Lc";
+		start = end = 255;
+		if (full)
+			start = 1;
 
-	dwSendLength = 5;
-	dwRecvLength = sizeof(r);
+		for (len_o = start; len_o <= end; len_o++)
+		{
+			s[0] = 0x80;
+			s[1] = 0x34;
+			if (len_o > 255)
+			{
+				s[2] = 0x01;
+				s[3] = len_o-256;
+			}
+			else
+			{
+				s[2] = 0x00;
+				s[3] = len_o;
+			}
+			s[4] = len_o;
 
-	for (i=0; i<len_o; i++)
-		e[i] = i;
-	e[i++] = 0x90;
-	e[i++] = 0x00;
-	e_length = len_o+2;
+			dwSendLength = 5;
+			dwRecvLength = sizeof(r);
 
-	if (exchange(text, lun, SendPci, &RecvPci,
-		s, dwSendLength, r, &dwRecvLength, e, e_length))
-		goto end;
+			for (i=0; i<len_o; i++)
+				e[i] = i;
+			e[i++] = 0x90;
+			e[i++] = 0x00;
+			e_length = len_o+2;
 
-	/* Case 4, TPDU */
-	/*
-	 * len_i
-	 * 248 (0xF8) is max size for one USB or GBP paquet
-	 * 255 (0xFF) maximum, 1 minimum
-	 *
-	 * len_o
-	 * 252  (0xFC) is max size for one USB or GBP paquet
-	 * 256 (0x100) maximum, 1 minimum
-	 */
-	text = "Case 4, TPDU: CLA INS P1 P2 Lc Data, L(Cmd) = 5 + Lc";
-	len_i = 2; //255;
-	len_o = 3; //256;
+			if (exchange(text, lun, SendPci, &RecvPci,
+				s, dwSendLength, r, &dwRecvLength, e, e_length))
+				goto end;
+		}
 
-	s[0] = 0x80;
-	s[1] = 0x24;
-	if (len_o > 255)
-	{
-		s[2] = 0x01;
-		s[3] = len_o-256;
+#if 0
+		/* Case 3, length too short */
+		text = "Case 3, length too short: CLA INS P1 P2 Lc Data, L(Cmd) = 5 + Lc";
+		len_o = 20;
+
+		s[0] = 0x80;
+		s[1] = 0x3C;
+		if (len_o > 255)
+		{
+			s[2] = 0x01;
+			s[3] = len_o-256;
+		}
+		else
+		{
+			s[2] = 0x00;
+			s[3] = len_o;
+		}
+		s[4] = len_o-10;
+
+		dwSendLength = 5;
+		dwRecvLength = sizeof(r);
+
+		if (tpdu)
+		{
+			for (i=0; i<len_o; i++)
+				e[i] = i;
+			e[i++] = 0x90;
+			e[i++] = 0x00;
+			e_length = len_o+2;
+		}
+		else
+		{
+			e[0] = 0x6C;
+			e[1] = len_o;
+			e_length = 2;
+		}
+
+		if (exchange(text, lun, SendPci, &RecvPci,
+			s, dwSendLength, r, &dwRecvLength, e, e_length))
+			goto end;
+#endif
+
+#if 0
+		/* Case 3, length too long */
+		text = "Case 3, length too long: CLA INS P1 P2 Lc Data, L(Cmd) = 5 + Lc";
+		len_o = 20;
+
+		s[0] = 0x80;
+		s[1] = 0x3C;
+		if (len_o > 255)
+		{
+			s[2] = 0x01;
+			s[3] = len_o-256;
+		}
+		else
+		{
+			s[2] = 0x00;
+			s[3] = len_o;
+		}
+		s[4] = len_o+10;
+
+		dwSendLength = 5;
+		dwRecvLength = sizeof(r);
+
+		if (tpdu)
+		{
+			for (i=0; i<len_o; i++)
+				e[i] = i;
+			e[i++] = 0x90;
+			e[i++] = 0x00;
+			e_length = len_o+2;
+		}
+		else
+		{
+			e[0] = 0x6C;
+			e[1] = len_o;
+			e_length = 2;
+		}
+
+		if (exchange(text, lun, SendPci, &RecvPci,
+			s, dwSendLength, r, &dwRecvLength, e, e_length))
+			goto end;
+#endif
 	}
-	else
+
+	if (cases & CASE4)
 	{
-		s[2] = 0x00;
-		s[3] = len_o;
-	}
-	s[4] = len_i;
+		if (tpdu)
+		{
+			/* Case 4, TPDU */
+			/*
+			 * len_i
+			 * 248 (0xF8) is max size for one USB or GBP paquet
+			 * 255 (0xFF) maximum, 1 minimum
+			 *
+			 * len_o
+			 * 252  (0xFC) is max size for one USB or GBP paquet
+			 * 256 (0x100) maximum, 1 minimum
+			 */
+			start = end = 255;
+			if (full)
+				start = 1;
 
-	for (i=0; i<len_i; i++)
-		s[5+i] = i;
+			for (len_i = start; len_i <= end; len_i++)
+			{
+				text = "Case 4, TPDU: CLA INS P1 P2 Lc Data, L(Cmd) = 5 + Lc";
+				len_o = 256 - len_i;
 
-	dwSendLength = len_i + 5;
-	dwRecvLength = sizeof(r);
+				s[0] = 0x80;
+				s[1] = 0x36;
+				if (len_o > 255)
+				{
+					s[2] = 0x01;
+					s[3] = len_o-256;
+				}
+				else
+				{
+					s[2] = 0x00;
+					s[3] = len_o;
+				}
+				s[4] = len_i;
 
-	e[0] = 0x61;
-	e[1] = len_o & 0xFF;
-	e_length = 2;
+				for (i=0; i<len_i; i++)
+					s[5+i] = i;
 
-	if (exchange(text, lun, SendPci, &RecvPci,
-		s, dwSendLength, r, &dwRecvLength, e, e_length))
-		goto end;
+				dwSendLength = len_i + 5;
+				dwRecvLength = sizeof(r);
 
-	/* Get response */
-	text = "Case 4, TPDU, Get response: ";
-	s[0] = 0x00;
-	s[1] = 0xC0;
-	s[2] = 0x00;
-	s[3] = 0x00;
-	s[4] = r[1]; /* SW2 of previous command */
+				e[0] = 0x61;
+				e[1] = len_o & 0xFF;
+				e_length = 2;
 
-	dwSendLength = 5;
-	dwRecvLength = sizeof(r);
+				if (exchange(text, lun, SendPci, &RecvPci,
+					s, dwSendLength, r, &dwRecvLength, e, e_length))
+					goto end;
 
-	for (i=0; i<len_o; i++)
-		e[i] = i;
-	e[i++] = 0x90;
-	e[i++] = 0x00;
-	e_length = len_o+2;
+				/* Get response */
+				text = "Case 4, TPDU, Get response: ";
+				s[0] = 0x80;
+				s[1] = 0xC0;
+				s[2] = 0x00;
+				s[3] = 0x00;
+				s[4] = r[1]; /* SW2 of previous command */
 
-	if (exchange(text, lun, SendPci, &RecvPci,
-		s, dwSendLength, r, &dwRecvLength, e, e_length))
-		goto end;
+				dwSendLength = 5;
+				dwRecvLength = sizeof(r);
 
-	/* Case 4, APDU */
-	/*
-	 * len_i
-	 * 248 (0xF8) is max size for one USB or GBP paquet
-	 * 255 (0xFF) maximum, 1 minimum
-	 *
-	 * len_o
-	 * 252  (0xFC) is max size for one USB or GBP paquet
-	 * 256 (0x100) maximum, 1 minimum
-	 */
-	text = "Case 4, APDU: CLA INS P1 P2 Lc Data Le, L(Cmd) = 5 + Lc +1";
-	len_i = 2; //255;
-	len_o = 3; //256;
+				for (i=0; i<len_o; i++)
+					e[i] = i;
+				e[i++] = 0x90;
+				e[i++] = 0x00;
+				e_length = len_o+2;
 
-	s[0] = 0x80;
-	s[1] = 0x24;
-	if (len_o > 255)
-	{
-		s[2] = 0x01;
-		s[3] = len_o-256;
-	}
-	else
-	{
-		s[2] = 0x00;
-		s[3] = len_o;
-	}
-	s[4] = len_i;
+				if (exchange(text, lun, SendPci, &RecvPci,
+					s, dwSendLength, r, &dwRecvLength, e, e_length))
+					goto end;
+			}
+		}
 
-	for (i=0; i<len_i; i++)
-		s[5+i] = i;
-	s[5+len_i] = len_o & 0xFF;
+		if (apdu)
+		{
+			/* Case 4, APDU */
+			/*
+			 * len_i
+			 * 248 (0xF8) is max size for one USB or GBP paquet
+			 * 255 (0xFF) maximum, 1 minimum
+			 *
+			 * len_o
+			 * 252  (0xFC) is max size for one USB or GBP paquet
+			 * 256 (0x100) maximum, 1 minimum
+			 */
+			text = "Case 4, APDU: CLA INS P1 P2 Lc Data Le, L(Cmd) = 5 + Lc +1";
+			start = end = 255;
+			if (full)
+				start = 1;
 
-	dwSendLength = len_i + 6;
-	dwRecvLength = sizeof(r);
+			for (len_i = start; len_i <= end; len_i++)
+			{
+				len_o = 256 - len_i;
 
-	for (i=0; i<len_o; i++)
-		e[i] = i;
-	e[i++] = 0x90;
-	e[i++] = 0x00;
-	e_length = len_o+2;
+				s[0] = 0x80;
+				s[1] = 0x36;
+				if (len_o > 255)
+				{
+					s[2] = 0x01;
+					s[3] = len_o-256;
+				}
+				else
+				{
+					s[2] = 0x00;
+					s[3] = len_o;
+				}
+				s[4] = len_i;
 
-	if (exchange(text, lun, SendPci, &RecvPci,
-		s, dwSendLength, r, &dwRecvLength, e, e_length))
-		goto end;
+				for (i=0; i<len_i; i++)
+					s[5+i] = i;
+				s[5+len_i] = len_o & 0xFF;
+
+				dwSendLength = len_i + 6;
+				dwRecvLength = sizeof(r);
+
+				for (i=0; i<len_o; i++)
+					e[i] = i;
+				e[i++] = 0x90;
+				e[i++] = 0x00;
+				e_length = len_o+2;
+
+				if (exchange(text, lun, SendPci, &RecvPci,
+					s, dwSendLength, r, &dwRecvLength, e, e_length))
+					goto end;
+			}
+		}
+	}
 
 end:
 	/* Close */
@@ -485,12 +691,20 @@
 		return 1;
 	}
 
-	for (i=0; i<e_length; i++)
+	/* check the received data */
+	for (i=0; i<*r_length; i++)
 		if (r[i] != e[i])
 		{
 			printf("ERROR byte %d: expected 0x%02X, got 0x%02X\n", i, e[i], r[i]);
 			return 1;
 		}
+
+	/* check the received length */
+	if (*r_length != e_length)
+	{
+		printf("ERROR: Expected %d bytes and received %ld\n", e_length, *r_length);
+		return 1;
+	}
 
 	printf("--------> OK\n");