Hi,

[sigh, not sure what happens here, but musclecard.com and my companies
mailserver don't like each other, thus posted via my private account]

Here comes a series of patches against Eric Piel's tree of the O2Micro
smartcard reader driver [1]. This allows me to use the driver over some
recent 2.6.24-rc kernel during daily work on my FuSie Lifebook 8110
(built-in reader).

Apply the patches in the following order (or use quilt):

fix-64-bit-issues.patch
- Fix warning
- Allow for building the ozctapi lib on x86-64

fix-reader-extension-alloc.patch
- obvious bug (once spotted :) ) that caused nasty oopses

fix-hang.patch
- use sleeping delays instead of busy-wait
- reduce some fairly conservative timeouts
- notes:
  o may cause regressions on hardware that needed such long timeouts
  o may open new race windows (but the code already has some)

fix-rsplen-overflow.patch
- an overflow on reading larger files (>256 bytes) prevented obtaining
  the most useful data from my ID card

remove-open-check.patch
- these checks are pointless (the code is racy anyway), and instead they
  cause troubles during hibernation when my box triggers an
  eject/insert cycle of the PCMCIA card while some application is still
  keeping the CT-API open. Actually, the kernel<->lib API needs some
  reworking, but this is an acceptable workaround for now.

detect-status-errors.patch
- let the CT-API return a useful state in case someone pulled the
  smartcard e.g.

So much for now. Feedback would be very appreciated. Are there users out
there who are already happy with the current code base? If so, please
let me know if some of those patches cause regressions for you.

Beyond this, are there plans to work on this driver, push it in some SCM
repository (on sourceforge, gna, etc.), improve it towards mainline
specifically, ...?

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
fix-64-bit-issues.patch
fix-reader-extension-alloc.patch
fix-hang.patch
fix-rsplen-overflow.patch
remove-open-check.patch
detect-status-errors.patch
---
 src/ozctapi/Makefile  |    2 +-
 src/ozscrlx/ozscrlx.c |    4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

Index: o2scr-new/src/ozscrlx/ozscrlx.c
===================================================================
--- o2scr-new.orig/src/ozscrlx/ozscrlx.c
+++ o2scr-new/src/ozscrlx/ozscrlx.c
@@ -810,13 +810,13 @@ static inline void o2scr_writeb(u8 *addr
 static inline u8 o2scr_inb(u8 *address)
 {
 	unsigned short us;
-	us = inw((unsigned)address);
+	us = inw((unsigned long)address);
 	return (u8) (us >> 8);
 }
 
 static inline void o2scr_outb(u8 *address, u8 byte)
 {
-	outw((u16) byte << 8, (unsigned)address);
+	outw((u16) byte << 8, (unsigned long)address);
 }
 
 static inline void o2scr_writel(unsigned long *address, unsigned long ul)
Index: o2scr-new/src/ozctapi/Makefile
===================================================================
--- o2scr-new.orig/src/ozctapi/Makefile
+++ o2scr-new/src/ozctapi/Makefile
@@ -5,7 +5,7 @@
 #======================================================
 
 
-CC       = gcc -Wall -O2 -DCPU_ICAP_PC -I/usr/include/PCSC
+CC       = gcc -Wall -O2 -DCPU_ICAP_PC -I/usr/include/PCSC -fPIC
 LD       = ld
 IXOZOBJ  = ctapi.o ifdhandler.o
 IXOZNAME = lib_OZSCR.so
---
 src/ozscrlx-2.6.13/ozscrlx.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: o2scr-new/src/ozscrlx/ozscrlx.c
===================================================================
--- o2scr-new.orig/src/ozscrlx/ozscrlx.c
+++ o2scr-new/src/ozscrlx/ozscrlx.c
@@ -600,7 +600,7 @@ static int ozscr_probe(struct pcmcia_dev
 	}
 
 	/* Allocate space for private device-specific data */
-	dev->o2scr_reader = kzalloc(sizeof(READER_EXTENSION *), GFP_KERNEL);
+	dev->o2scr_reader = kzalloc(sizeof(READER_EXTENSION), GFP_KERNEL);
 	if (dev->o2scr_reader == NULL) {
 		dprintk("allocate READER_EXTENSION fail\n");
 		goto ErrHandle;
---
 src/ozscrlx-2.6.13/ozscrlx.c |   92 +++++++++++++++++++++----------------------
 1 file changed, 46 insertions(+), 46 deletions(-)

Index: o2scr-new/src/ozscrlx/ozscrlx.c
===================================================================
--- o2scr-new.orig/src/ozscrlx/ozscrlx.c
+++ o2scr-new/src/ozscrlx/ozscrlx.c
@@ -858,7 +858,7 @@ static unsigned int CmdExecuteWithTimeOu
 			break;
 		}
 
-		mdelay(1);
+		msleep(1);
 	}
 
 	*status_exch = readw(membase + STATUS_EXCH);
@@ -1050,14 +1050,14 @@ static unsigned int CmdResetInterface(RE
 	writew(RESET_EXE, membase + EXE);
 
 	/*Wait for at least 1 microseconds */
-	mdelay(1);
+	msleep(1);
 
 	/*EXE.RESET_EXE = 0 */
 	writew(0x0000, membase + EXE);
 
 	/*Wait for at least 1 microseconds */
-	// XXX wait a minute, you said MICROseconds ? isn't mdelay for MILLIseconds !?
-	mdelay(1);
+	// XXX wait a minute, you said MICROseconds ? isn't msleep for MILLIseconds !?
+	msleep(1);
 
 	/*MODE.EDC = 1; Since the SMCLIB will calculate the EDC for us */
 	uc = o2scr_readb(membase + MODE);
@@ -1381,7 +1381,7 @@ static void man_start_receiving(void)
 	/*Receiving Mode */
 	o2scr_writeb(sync_membase + MANUAL_E_R, 0xE0);
 
-	mdelay(1);
+	msleep(1);
 }
 
 static void man_start_emitting(void)
@@ -1404,7 +1404,7 @@ static void man_vcc_on(void)
 {
 	/*VCC - Power On */
 	o2scr_outb(&sync_IOBase->MANUAL_IN, 0x80);
-	mdelay(1);
+	msleep(1);
 	ct = o2scr_inb(&sync_IOBase->MANUAL_OUT);
 }
 
@@ -1412,7 +1412,7 @@ static void man_vcc_on(void)
 static void man_vcc_off(void)
 {
 	o2scr_outb(&sync_IOBase->MANUAL_IN, 0x00);
-	mdelay(1);
+	msleep(1);
 	ct = o2scr_inb(&sync_IOBase->MANUAL_OUT);
 }
 #endif
@@ -1442,10 +1442,10 @@ static void man_send_command(u8 control,
 	controlDWord = ((u32) data << 16 | (u32) address << 8 | (u32) control);
 
 	man_low(RST);
-	mdelay(1);
+	msleep(1);
 	man_start_emitting();
 
-	mdelay(1);
+	msleep(1);
 	man_high(RST);
 	for (i = 0; i < 24; i++) {
 		if (controlDWord & (1 << i))
@@ -1453,14 +1453,14 @@ static void man_send_command(u8 control,
 		else
 			man_low(IO);
 
-		mdelay(1);
+		msleep(1);
 		man_high(CLK);
 
-		mdelay(1);
+		msleep(1);
 		man_low(CLK);
 	}
 	man_start_receiving();
-	mdelay(1);
+	msleep(1);
 	man_low(RST);
 }
 
@@ -1473,22 +1473,22 @@ static u8 man_readb(u16 addressWord)
 
 	man_send_command(control, address, 0x00);
 
-	mdelay(1);
+	msleep(1);
 	set_manual_mode();
-	mdelay(1);
+	msleep(1);
 	man_high(CLK);
-	mdelay(1);
+	msleep(1);
 	man_low(CLK);
 	for (i = 0; i < 8; i++) {
-		mdelay(1);
+		msleep(1);
 		man_high(CLK);
 
 		if (man_is_read_io())
 			data |= 1 << i;
-		mdelay(1);
+		msleep(1);
 		man_low(30);	// XXX what is this port?
 	}
-	mdelay(1);
+	msleep(1);
 	man_high(RST);
 
 	return data;
@@ -1525,16 +1525,16 @@ static unsigned int man_writeb(u16 addre
 	chkCycle = duraCycle - 3;
 
 	man_send_command(control, address, data);
-	mdelay(1);
+	msleep(1);
 	for (i = 0; i < duraCycle; i++) {
-		mdelay(1);
+		msleep(1);
 		man_high(CLK);
 		if (i == chkCycle) {
 			ackData = man_is_read_io();
 			if (ackData)
 				ret = STATUS_SUCCESS;
 		}
-		mdelay(1);
+		msleep(1);
 		man_low(CLK);
 	}
 
@@ -1553,18 +1553,18 @@ static void SyncReset(u8 astr[4])
 
 	set_manual_mode();
 	man_vcc_on();
-	mdelay(1);
+	msleep(1);
 	man_high(RST);
 
-	mdelay(1);
+	msleep(1);
 	man_high(CLK);
-	mdelay(1);
+	msleep(1);
 	man_low(CLK);
 
-	mdelay(1);
+	msleep(1);
 	man_low(RST);
 
-	mdelay(1);
+	msleep(1);
 	for (i = 0; i < 4; i++) {
 		c = 0;
 		for (j = 0; j < 8; j++) {
@@ -1573,9 +1573,9 @@ static void SyncReset(u8 astr[4])
 			if (man_is_read_io())
 				c |= 1 << j;
 
-			mdelay(1);
+			msleep(1);
 			man_low(CLK);
-			mdelay(1);
+			msleep(1);
 		}
 
 		astr[i] = c;
@@ -1703,7 +1703,7 @@ static unsigned int CmdDeactivate(READER
 
 	/*Power off */
 	ret = CmdExecute(pRdrExt, POF_EXE, &status_exch);
-	mdelay(1);
+	msleep(1);
 	us = readw(membase + STATUS_EXCH);
 	if (us & CRD_ON)
 		ret = STATUS_UNSUCCESSFUL;
@@ -1838,7 +1838,7 @@ static unsigned int PscrWriteDirectWithF
 			if (us == 0)
 				break;
 
-			mdelay(1);
+			msleep(1);
 		}
 	}
 
@@ -1857,7 +1857,7 @@ static unsigned int PscrWriteDirectWithF
 		if (us == fifoLev)
 			break;
 
-		mdelay(1);
+		msleep(1);
 	}
 
 	/* Check what kind of error we got */
@@ -2152,12 +2152,12 @@ static unsigned int scT1ChangeIFSD(READE
 			return SC_EXIT_IO_ERROR;
 		}
 
-		mdelay(3000);	//XXX 3s, that's a long delay
+		msleep(10);	//XXX 3s, that's a long delay
 
 		rblocklen = MAX_T1_BLOCK_SIZE;
 		ret = ReadFIFO(pRdrExt, rblock, &rblocklen);
 		if (ret == STATUS_SUCCESS) {
-			if ((rblocklen == blocklen) && (rblock[1] == 0xE1) &&
+			if (/*(rblocklen == blocklen) &&*/ (rblock[1] == 0xE1) &&
 			    scT1CheckRc(pRdrExt, rblock, &rblocklen)) {
 				pRdrExt->T1.ifsreq = TRUE;
 				pRdrExt->T1.ifsd = rblock[3];
@@ -2543,7 +2543,7 @@ static unsigned int cb_t1_transmit_sbloc
 		return SC_EXIT_IO_ERROR;
 	}
 	pRdrExt->T1.ifsc = rblock[3];
-	mdelay(3000);		//XXX 3s, quite long
+	msleep(10);		//XXX 3s, quite long
 
 	return SC_EXIT_OK;
 }
@@ -2569,7 +2569,7 @@ static unsigned int cb_t1_transmit_sbloc
 		return SC_EXIT_IO_ERROR;
 	}
 	/* Wait BWT. */
-	mdelay(3000);		//XXX 3s, quite long
+	msleep(10);		//XXX 3s, quite long
 	ret = ReadFIFO(pRdrExt, rblock, rblocklen);
 	if (ret) {
 		printk(KERN_WARNING MODULE_NAME "ReadFIFO() failed\n");
@@ -2788,12 +2788,12 @@ static unsigned int VerifyByte(u8 contro
 	int i;
 
 	man_send_command(control, address, data);
-	mdelay(1);
+	msleep(1);
 
 	for (i = 0; i < 2; i++) {
-		mdelay(1);
+		msleep(1);
 		man_high(CLK);
-		mdelay(1);
+		msleep(1);
 		ackData = man_is_read_io();
 		man_low(CLK);
 		if (!ackData && (i == 1))
@@ -2810,12 +2810,12 @@ static unsigned int VerifyCounter(u8 con
 	int i;
 
 	man_send_command(control, address, data);
-	mdelay(1);
+	msleep(1);
 	for (i = 0; i < 103; i++) {
-		mdelay(1);
+		msleep(1);
 		man_high(CLK);
 		ackData = man_is_read_io();	// XXX is it really necessary to read it everytime?
-		mdelay(1);
+		msleep(1);
 		man_low(CLK);
 		if (ackData && (i == 100))
 			ret = STATUS_SUCCESS;
@@ -2845,17 +2845,17 @@ static unsigned int VerifyData(READER_EX
 		 (trials == 2) ? 0x80 : 0x00; */
 
 		ret = VerifyCounter(0xF2, 0xFD, data);
-		mdelay(1);
+		msleep(1);
 
 		if (ret == STATUS_SUCCESS) {
 			/* enter first PSC-code byte */
 			ret = VerifyByte(0xCD, 0xFE, pRequest[5]);
-			mdelay(1);
+			msleep(1);
 
 			if (ret == STATUS_SUCCESS) {
 				/* enter second PSC-code byte */
 				ret = VerifyByte(0xCD, 0xFF, pRequest[6]);
-				mdelay(1);
+				msleep(1);
 			}
 		}
 
@@ -2883,13 +2883,13 @@ static unsigned int ChangeVerifyData(REA
 
 	/* update first PSC-code byte */
 	ret = VerifyCounter(0xF3, 0xFE, pRequest[8]);
-	mdelay(1);
+	msleep(1);
 
 	if (ret == STATUS_SUCCESS) {
 		/* update second PSC-code byte */
 		ret = VerifyCounter(0xF3, 0xFF, pRequest[9]);
 
-		mdelay(1);
+		msleep(1);
 	}
 
 	pRdrExt->SmartcardReply.BufferLength = 2;
Index: o2scr-new/src/ozscrlx/ozscrlx.c
===================================================================
--- o2scr-new.orig/src/ozscrlx/ozscrlx.c
+++ o2scr-new/src/ozscrlx/ozscrlx.c
@@ -2430,7 +2430,7 @@ static unsigned int cb_t1_transmit_ibloc
 					  u8 *rblock, unsigned long *rblocklen,
 					  u8 *block2, unsigned long *block2len,
 					  int *ib_other_err_cntr, int *ierrcntr,
-					  u8 *rsp, u8 *rsplen)
+					  u8 *rsp, unsigned long *rsplen)
 {
 	unsigned int ret;
 	dprintk("/* I-Block */\n");
@@ -2499,7 +2499,7 @@ static unsigned int cb_t1_transmit_ibloc
 		    (pRdrExt->T1.cse == SC_APDU_CASE_4_SHORT)) {
 			unsigned long cpylen;
 			/* Copy response and SW. */
-			cpylen = min(*rsplen - 2, SC_GENERAL_SHORT_DATA_SIZE);	// XXX in reallity it's always *rsplen-2 because it can't be > 256
+			cpylen = min(*rsplen - 2, (unsigned long)SC_GENERAL_SHORT_DATA_SIZE);	// XXX in reallity it's always *rsplen-2 because it can't be > 256
 			memcpy(pReply, rsp, cpylen);
 			memcpy(pReply + cpylen, &rsp[*rsplen - 2], 2);
 			pRdrExt->SmartcardReply.BufferLength = cpylen + 2;
@@ -2641,7 +2641,7 @@ static unsigned int CBT1Transmit(READER_
 	u8 *rblock = pRdrExt->SmartcardReply.Buffer;
 	unsigned long rblocklen;
 	u8 rsp[SC_GENERAL_SHORT_DATA_SIZE + 3];
-	u8 rsplen = 0;
+	unsigned long rsplen = 0;
 
 	BOOLEAN more = TRUE;	/* More data to send. */
 	BOOLEAN lastiicc = FALSE;	/* It's ICCs turn to send I-Blocks. */
---
 src/ozscrlx/ozscrlx.c |    7 -------
 1 file changed, 7 deletions(-)

Index: o2scr-new/src/ozscrlx/ozscrlx.c
===================================================================
--- o2scr-new.orig/src/ozscrlx/ozscrlx.c
+++ o2scr-new/src/ozscrlx/ozscrlx.c
@@ -244,10 +244,6 @@ static int ozscr_open(struct inode *inod
 	if (p_dev == NULL || !pcmcia_dev_present(p_dev))
 		return -ENODEV;
 
-	/* Only one process may use the reader */
-	if (p_dev->open > 0)
-		return -EBUSY;
-	++p_dev->open;
 	return 0;		//XXX should this be set as non-seekable ?
 }
 
@@ -264,9 +260,6 @@ static int ozscr_close(struct inode *ino
 	if (p_dev == NULL || !pcmcia_dev_present(p_dev))
 		return -ENODEV;
 
-	/* Make device available again */
-	--(p_dev->open);
-
 	return 0;
 }
 
---
 src/ozctapi/ctapi.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

Index: o2scr-new/src/ozctapi/ctapi.c
===================================================================
--- o2scr-new.orig/src/ozctapi/ctapi.c
+++ o2scr-new/src/ozctapi/ctapi.c
@@ -260,6 +260,10 @@ int CT_data( unsigned short ctn, unsigne
             if (*lr < 3) return ERR_MEMORY; /* Return buffer too small */
             /* Ask for status */
             IXret = ioctl(handle, OZSCR_STATUS, &RdrExt);
+            if (IXret < 0) {
+                *lr = 0;
+                return ERR_TRANS;
+            }
             ixpar = (unsigned char)(IXret) & 0xC0;
             ixpar = ixpar >> 6;
             *lr = 3;
@@ -276,8 +280,6 @@ int CT_data( unsigned short ctn, unsigne
                 case 1: /* Card not inserted, and inactive */
                     rsp[0] = 1;
                     break;
-                default: /* Should not happen. Report as error. */
-                    IretVal = IX_ICC_ILLEGAL_PAR;
             }
             rsp[1] = 0x90;
             rsp[2] = 0x00;

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Muscle mailing list
[email protected]
http://lists.drizzle.com/mailman/listinfo/muscle

Reply via email to