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