This patch adds a workaround for unusual behaviour of Broadcom
BCM5880/5881 readers. They misreport an absent card as "Hardware
Error" in GetSlotStatus.

To work around it, we turn the HW_ERROR answer to GetSlotStatus
into "No error, no card inserted".

Since we need some way to look up the required quirk based on
USB vendor/product ID, this patch adds some simple quirk lookup
functions which can also be used for future quirks.

diff --git a/src/commands.c b/src/commands.c
index a84701d..7642f08 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -70,6 +70,73 @@ static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int 
reader_index,
 
 static void i2dw(int value, unsigned char *buffer);
 
+/*
+ * Quirks for unusual/broken readers
+ */
+
+enum {
+       /*
+        * Quirk for readers which handle GetSlotStatus badly
+        * when no card is inserted. Known to happen with BCM5880.
+        * Makes us map HW_ERROR to "no card inserted".
+        */
+       QUIRK_SLOTSTATUS_HWERR = 1,
+};
+
+struct ccid_quirk {
+       /*
+        * Reader as VendorID << 16 + ProductID. compare readerID in
+        * _ccid_descriptor.
+        */
+       int readerID;
+
+       /*
+        * Binary OR of quirks to apply.
+        */
+       unsigned int quirks;
+};
+
+static struct ccid_quirk ccid_quirktab[] = {
+       /*
+        * Broadcom BCM5880/5881
+        */
+       { 0x0a5c5800, QUIRK_SLOTSTATUS_HWERR },
+       { 0x0a5c5801, QUIRK_SLOTSTATUS_HWERR },
+};
+
+static int ccid_quirk_lookup(_ccid_descriptor *ccid, unsigned int *quirks)
+{
+       int i;
+
+       for (i=0; i < sizeof(ccid_quirktab)/sizeof(ccid_quirktab[0]); i++) {
+               struct ccid_quirk *q = &ccid_quirktab[i];
+
+               if (ccid->readerID == q->readerID) {
+                       *quirks = q->quirks;
+                       return 1;
+               }
+       }
+
+       *quirks = 0;
+       return 0;
+}
+
+/*
+ * Check for specific quirk flag; Returns 1 if quirk is required.
+ */
+
+static int ccid_quirk_required(_ccid_descriptor *ccid, int flag)
+{
+       int quirks;
+
+       if (ccid_quirk_lookup(ccid, &quirks) == 0)
+               return 0;
+
+       if ((quirks & flag) == flag)
+               return 1;
+
+       return 0;
+}
 
 /*****************************************************************************
  *
@@ -1009,8 +1076,39 @@ again_status:
 #endif
                ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, 
__FUNCTION__);    /* bError */
 
+               /*
+                * LSE: Special case for BCM5880/5881 readers since they
+                * answer with HW_ERROR if no card is inserted. We still
+                * log the error but turn it into "no card inserted".
+                */
+
+               if (ccid_quirk_required(ccid_descriptor, 
QUIRK_SLOTSTATUS_HWERR))
+               {
+                       /*
+                        * Override status/error fields to have status as if
+                        * no card was inserted.
+                        */
+
+                       log_msg(PCSC_LOG_ERROR, "%s:%d:%s %s",
+                               __FILE__, __LINE__, __FUNCTION__,
+                               "Applying QUIRK_SLOTSTATUS_HWERR");
+
+                       /*
+                        * bmICCStatus: 2 ("No ICC present")
+                        * bmCommandStatus: 0 ("Processed without error")
+                        */
+
+                       buffer[STATUS_OFFSET] = 0x02;
+
+                       /*
+                        * Clear error register.
+                        */
+
+                       buffer[ERROR_OFFSET] = 0x00;
+               }
+
                /* card absent or mute is not an communication error */
-               if (buffer[ERROR_OFFSET] != 0xFE)
+               else if (buffer[ERROR_OFFSET] != 0xFE)
                        return_value = IFD_COMMUNICATION_ERROR;
        }
 
_______________________________________________
Muscle mailing list
[email protected]
http://lists.drizzle.com/mailman/listinfo/muscle

Reply via email to