LONG IFDControl(READER_CONTEXT * rContext, DWORD ControlCode, LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength, LPDWORD BytesReturned) { RESPONSECODE rv = IFD_SUCCESS; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD); #endif if (rContext->version < IFD_HVERSION_3_0) return SCARD_E_UNSUPPORTED_FEATURE; #ifndef PCSCLITE_STATIC_DRIVER IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl; #endif /* LOCK THIS CODE REGION */ (void)pthread_mutex_lock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER rv = (*IFDH_control) (rContext->slot, ControlCode, TxBuffer, TxLength, RxBuffer, RxLength, BytesReturned); #elif defined(IFDHANDLERv3) rv = IFDHControl(rContext->slot, ControlCode, TxBuffer, TxLength, RxBuffer, RxLength, BytesReturned); #endif /* END OF LOCKED REGION */ (void)pthread_mutex_unlock(rContext->mMutex); if (rv == IFD_SUCCESS) return SCARD_S_SUCCESS; else { Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); Log3(PCSC_LOG_DEBUG, "ControlCode: 0x%.8lX BytesReturned: %ld", ControlCode, *BytesReturned); LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength); LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *BytesReturned); if (rv == IFD_NO_SUCH_DEVICE) { (void)SendHotplugSignal(); return SCARD_E_READER_UNAVAILABLE; } if ((IFD_ERROR_NOT_SUPPORTED == rv) || (IFD_NOT_SUPPORTED == rv)) return SCARD_E_UNSUPPORTED_FEATURE; if (IFD_ERROR_INSUFFICIENT_BUFFER ==rv) return SCARD_E_INSUFFICIENT_BUFFER; return SCARD_E_NOT_TRANSACTED; } }
LONG IFDControl(PREADER_CONTEXT rContext, DWORD ControlCode, LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength, LPDWORD BytesReturned) { RESPONSECODE rv = IFD_SUCCESS; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD); #endif if (rContext->dwVersion < IFD_HVERSION_3_0) return SCARD_E_UNSUPPORTED_FEATURE; #ifndef PCSCLITE_STATIC_DRIVER IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl; #endif /* LOCK THIS CODE REGION */ (void)SYS_MutexLock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER rv = (*IFDH_control) (rContext->dwSlot, ControlCode, TxBuffer, TxLength, RxBuffer, RxLength, BytesReturned); #else rv = IFDHControl(rContext->dwSlot, ControlCode, TxBuffer, TxLength, RxBuffer, RxLength, BytesReturned); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); if (rv == IFD_SUCCESS) return SCARD_S_SUCCESS; else { Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); Log3(PCSC_LOG_DEBUG, "ControlCode: 0x%.8LX BytesReturned: %ld", ControlCode, *BytesReturned); LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength); LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *BytesReturned); if (rv == IFD_NO_SUCH_DEVICE) { // (void)SendHotplugSignal(); return SCARD_E_READER_UNAVAILABLE; } return SCARD_E_NOT_TRANSACTED; } }
LONG IFDControl_v2(PREADER_CONTEXT rContext, PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength) { RESPONSECODE rv = IFD_SUCCESS; #ifndef PCSCLITE_STATIC_DRIVER RESPONSECODE(*IFDH_control_v2) (DWORD, PUCHAR, DWORD, /*@out@*/ PUCHAR, PDWORD); #endif if (rContext->dwVersion != IFD_HVERSION_2_0) return SCARD_E_UNSUPPORTED_FEATURE; #ifndef PCSCLITE_STATIC_DRIVER IFDH_control_v2 = rContext->psFunctions.psFunctions_v2.pvfControl; #endif /* LOCK THIS CODE REGION */ (void)SYS_MutexLock(rContext->mMutex); #ifndef PCSCLITE_STATIC_DRIVER rv = (*IFDH_control_v2) (rContext->dwSlot, TxBuffer, TxLength, RxBuffer, RxLength); #else rv = IFDHControl_v2(rContext->dwSlot, TxBuffer, TxLength, RxBuffer, RxLength); #endif /* END OF LOCKED REGION */ (void)SYS_MutexUnLock(rContext->mMutex); if (rv == IFD_SUCCESS) return SCARD_S_SUCCESS; else { Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength); LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *RxLength); return SCARD_E_NOT_TRANSACTED; } }
int get_atr(enum atr_modulation modulation, const unsigned char *in, size_t inlen, unsigned char *atr, size_t *atr_len) { unsigned char hb[0xff - 1], tck; size_t hb_len, idx, len; if (!in || !atr_len) return 0; /* get the Historical Bytes */ switch (modulation) { case ATR_ISO14443A_106: LogXxd(PCSC_LOG_DEBUG, "Will calculate ATR from this ATS payload: ", in, inlen); if (inlen) { idx = 1; /* Bits 5 to 7 tell if TA1/TB1/TC1 are available */ if (in[0] & 0x10) { // TA idx++; } if (in[0] & 0x20) { // TB idx++; } if (in[0] & 0x40) { // TC idx++; } if (idx < inlen) { hb_len = inlen - idx; memcpy(hb, in + idx, hb_len); Log3(PCSC_LOG_DEBUG, "Found %zu interface byte(s)" " and %zu historical byte(s)", idx - 2, hb_len); } else { hb_len = 0; } } else { hb_len = 0; } break; case ATR_ISO14443B_106: LogXxd(PCSC_LOG_DEBUG, "Will calculate ATR from this ATQB: ", in, inlen); if (inlen < 12) { Log1(PCSC_LOG_INFO, "ATQB too short " "to contain historical bytes"); hb_len = 0; break; } memcpy(hb, in + 5, 7); hb[7] = 0; hb_len = 8; break; case ATR_DEFAULT: hb_len = 0; break; default: /* for all other types: Empty ATR */ Log1(PCSC_LOG_INFO, "Returning empty ATR " "for card without APDU support."); *atr_len = 0; return 1; } /* length of ATR without TCK */ len = 4 + hb_len; if (*atr_len < len + 1) return 0; atr[0] = 0x3b; atr[1] = 0x80 + hb_len; atr[2] = 0x80; atr[3] = 0x01; memcpy(&atr[4], hb, hb_len); /* calculate TCK */ tck = atr[1]; for (idx = 2; idx < len; idx++) { tck ^= atr[idx]; } atr[len] = tck; *atr_len = len + 1; return 1; }
static void EHStatusHandlerThread(READER_CONTEXT * rContext) { LONG rv; const char *readerName; DWORD dwStatus; uint32_t readerState; int32_t readerSharing; DWORD dwCurrentState; DWORD dwAtrLen; /* * Zero out everything */ dwStatus = 0; readerName = rContext->readerState->readerName; rv = IFDStatusICC(rContext, &dwStatus); if ((SCARD_S_SUCCESS == rv) && (dwStatus & SCARD_PRESENT)) { #ifdef DISABLE_AUTO_POWER_ON rContext->readerState->cardAtrLength = 0; rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; readerState = SCARD_PRESENT; Log1(PCSC_LOG_INFO, "Skip card power on"); #else dwAtrLen = sizeof(rContext->readerState->cardAtr); rv = IFDPowerICC(rContext, IFD_POWER_UP, rContext->readerState->cardAtr, &dwAtrLen); rContext->readerState->cardAtrLength = dwAtrLen; /* the protocol is unset after a power on */ rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; if (rv == IFD_SUCCESS) { readerState = SCARD_PRESENT | SCARD_POWERED | SCARD_NEGOTIABLE; rContext->powerState = POWER_STATE_POWERED; Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_POWERED"); if (rContext->readerState->cardAtrLength > 0) { LogXxd(PCSC_LOG_INFO, "Card ATR: ", rContext->readerState->cardAtr, rContext->readerState->cardAtrLength); } else Log1(PCSC_LOG_INFO, "Card ATR: (NULL)"); } else { readerState = SCARD_PRESENT | SCARD_SWALLOWED; rContext->powerState = POWER_STATE_UNPOWERED; Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED"); Log3(PCSC_LOG_ERROR, "Error powering up card: %d 0x%04X", rv, rv); } #endif dwCurrentState = SCARD_PRESENT; } else { readerState = SCARD_ABSENT; rContext->readerState->cardAtrLength = 0; rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; dwCurrentState = SCARD_ABSENT; } /* * Set all the public attributes to this reader */ rContext->readerState->readerState = readerState; rContext->readerState->readerSharing = readerSharing = rContext->contexts; (void)EHSignalEventToClients(); while (1) { dwStatus = 0; rv = IFDStatusICC(rContext, &dwStatus); if (rv != SCARD_S_SUCCESS) { Log2(PCSC_LOG_ERROR, "Error communicating to: %s", readerName); /* * Set error status on this reader while errors occur */ rContext->readerState->readerState = SCARD_UNKNOWN; rContext->readerState->cardAtrLength = 0; rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; dwCurrentState = SCARD_UNKNOWN; (void)EHSignalEventToClients(); } if (dwStatus & SCARD_ABSENT) { if (dwCurrentState == SCARD_PRESENT || dwCurrentState == SCARD_UNKNOWN) { /* * Change the status structure */ Log2(PCSC_LOG_INFO, "Card Removed From %s", readerName); /* * Notify the card has been removed */ (void)RFSetReaderEventState(rContext, SCARD_REMOVED); rContext->readerState->cardAtrLength = 0; rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; rContext->readerState->readerState = SCARD_ABSENT; dwCurrentState = SCARD_ABSENT; rContext->readerState->eventCounter++; (void)EHSignalEventToClients(); } } else if (dwStatus & SCARD_PRESENT) { if (dwCurrentState == SCARD_ABSENT || dwCurrentState == SCARD_UNKNOWN) { #ifdef DISABLE_AUTO_POWER_ON rContext->readerState->cardAtrLength = 0; rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; rContext->readerState->readerState = SCARD_PRESENT; rContext->powerState = POWER_STATE_UNPOWERED; Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED"); readerState = SCARD_PRESENT; rv = IFD_SUCCESS; Log1(PCSC_LOG_INFO, "Skip card power on"); #else /* * Power and reset the card */ dwAtrLen = sizeof(rContext->readerState->cardAtr); rv = IFDPowerICC(rContext, IFD_POWER_UP, rContext->readerState->cardAtr, &dwAtrLen); rContext->readerState->cardAtrLength = dwAtrLen; /* the protocol is unset after a power on */ rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; if (rv == IFD_SUCCESS) { rContext->readerState->readerState = SCARD_PRESENT | SCARD_POWERED | SCARD_NEGOTIABLE; rContext->powerState = POWER_STATE_POWERED; Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_POWERED"); } else { rContext->readerState->readerState = SCARD_PRESENT | SCARD_SWALLOWED; rContext->powerState = POWER_STATE_UNPOWERED; Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED"); rContext->readerState->cardAtrLength = 0; } #endif dwCurrentState = SCARD_PRESENT; rContext->readerState->eventCounter++; Log2(PCSC_LOG_INFO, "Card inserted into %s", readerName); (void)EHSignalEventToClients(); if (rv == IFD_SUCCESS) { if (rContext->readerState->cardAtrLength > 0) { LogXxd(PCSC_LOG_INFO, "Card ATR: ", rContext->readerState->cardAtr, rContext->readerState->cardAtrLength); } else Log1(PCSC_LOG_INFO, "Card ATR: (NULL)"); } else Log1(PCSC_LOG_ERROR,"Error powering up card."); } } /* * Sharing may change w/o an event pass it on */ if (readerSharing != rContext->contexts) { readerSharing = rContext->contexts; rContext->readerState->readerSharing = readerSharing; (void)EHSignalEventToClients(); } if (rContext->pthCardEvent) { int ret; int timeout; #ifndef DISABLE_ON_DEMAND_POWER_ON if (POWER_STATE_POWERED == rContext->powerState) /* The card is powered but not yet used */ timeout = PCSCLITE_POWER_OFF_GRACE_PERIOD; else /* The card is already in use or not used at all */ #endif timeout = PCSCLITE_STATUS_EVENT_TIMEOUT; ret = rContext->pthCardEvent(rContext->slot, timeout); if (IFD_SUCCESS != ret) (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE); } else (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE); #ifndef DISABLE_ON_DEMAND_POWER_ON /* the card is powered but not used */ (void)pthread_mutex_lock(&rContext->powerState_lock); if (POWER_STATE_POWERED == rContext->powerState) { /* power down */ IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL); rContext->powerState = POWER_STATE_UNPOWERED; Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED"); /* the protocol is unset after a power down */ rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; } /* the card was in use */ if (POWER_STATE_GRACE_PERIOD == rContext->powerState) { /* the next state should be UNPOWERED unless the * card is used again */ rContext->powerState = POWER_STATE_POWERED; Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_POWERED"); } (void)pthread_mutex_unlock(&rContext->powerState_lock); #endif if (rContext->hLockId == 0xFFFF) { /* * Exit and notify the caller */ (void)EHSignalEventToClients(); Log1(PCSC_LOG_INFO, "Die"); rContext->hLockId = 0; (void)pthread_exit(NULL); } } }
/** * @brief parse an ATR * * @param[out] psExtension * @param[in] pucAtr ATR * @param[in] dwLength ATR length * @return */ short ATRDecodeAtr(PSMARTCARD_EXTENSION psExtension, const unsigned char *pucAtr, DWORD dwLength) { USHORT p; UCHAR K, TCK; /* MSN of T0/Check Sum */ UCHAR Y1i, T; /* MSN/LSN of TDi */ int i = 1; /* value of the index in TAi, TBi, etc. */ /* * Zero out everything */ p = K = TCK = Y1i = T = 0; #ifdef ATR_DEBUG if (dwLength > 0) LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength); #endif if (dwLength < 2) return 0; /** @retval 0 Atr must have TS and T0 */ /* * Zero out the bitmasks */ psExtension->CardCapabilities.AvailableProtocols = SCARD_PROTOCOL_UNDEFINED; psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_UNDEFINED; /* * Decode the TS byte */ if (pucAtr[0] == 0x3F) { /* Inverse convention used */ psExtension->CardCapabilities.Convention = SCARD_CONVENTION_INVERSE; } else if (pucAtr[0] == 0x3B) { /* Direct convention used */ psExtension->CardCapabilities.Convention = SCARD_CONVENTION_DIRECT; } else { memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION)); return 0; /** @retval 0 Unable to decode TS byte */ } /* * Here comes the platform dependant stuff */ /* * Decode the T0 byte */ Y1i = pucAtr[1] >> 4; /* Get the MSN in Y1 */ K = pucAtr[1] & 0x0F; /* Get the LSN in K */ p = 2; #ifdef ATR_DEBUG Log4(PCSC_LOG_DEBUG, "Conv: %02X, Y1: %02X, K: %02X", psExtension->CardCapabilities.Convention, Y1i, K); #endif /* * Examine Y1 */ do { short TAi, TBi, TCi, TDi; /* Interface characters */ TAi = (Y1i & 0x01) ? pucAtr[p++] : -1; TBi = (Y1i & 0x02) ? pucAtr[p++] : -1; TCi = (Y1i & 0x04) ? pucAtr[p++] : -1; TDi = (Y1i & 0x08) ? pucAtr[p++] : -1; #ifdef ATR_DEBUG Log9(PCSC_LOG_DEBUG, "TA%d: %02X, TB%d: %02X, TC%d: %02X, TD%d: %02X", i, TAi, i, TBi, i, TCi, i, TDi); #endif /* * Examine TDi to determine protocol and more */ if (TDi >= 0) { Y1i = TDi >> 4; /* Get the MSN in Y1 */ T = TDi & 0x0F; /* Get the LSN in K */ /* * Set the current protocol TD1 (first TD only) */ if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNDEFINED) { switch (T) { case 0: psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_T0; break; case 1: psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_T1; break; default: return 0; /** @retval 0 Unable to decode LNS */ } } #ifdef ATR_DEBUG Log2(PCSC_LOG_DEBUG, "T=%d Protocol Found", T); #endif if (0 == T) { psExtension->CardCapabilities.AvailableProtocols |= SCARD_PROTOCOL_T0; } else if (1 == T) { psExtension->CardCapabilities.AvailableProtocols |= SCARD_PROTOCOL_T1; } else if (15 == T) { psExtension->CardCapabilities.AvailableProtocols |= SCARD_PROTOCOL_T15; } else { /* * Do nothing for now since other protocols are not * supported at this time */ } } else Y1i = 0; /* test presence of TA2 */ if ((2 == i) && (TAi >= 0)) { T = TAi & 0x0F; #ifdef ATR_DEBUG Log2(PCSC_LOG_DEBUG, "Specific mode: T=%d", T); #endif switch (T) { case 0: psExtension->CardCapabilities.CurrentProtocol = psExtension->CardCapabilities.AvailableProtocols = SCARD_PROTOCOL_T0; break; case 1: psExtension->CardCapabilities.CurrentProtocol = psExtension->CardCapabilities.AvailableProtocols = SCARD_PROTOCOL_T1; break; default: return 0; /** @retval 0 Unable do decode T protocol */ } } if (p > MAX_ATR_SIZE) { memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION)); return 0; /** @retval 0 Maximum attribute size */ } /* next interface characters index */ i++; }
void EHStatusHandlerThread(PREADER_CONTEXT rContext) { LONG rv; LPCSTR lpcReader; DWORD dwStatus, dwReaderSharing; DWORD dwCurrentState; int pageSize = SYS_GetPageSize(); /* * Zero out everything */ dwStatus = 0; dwReaderSharing = 0; dwCurrentState = 0; secdebug("pcscd", "EHStatusHandlerThread: rContext: 0x%p", rContext); lpcReader = rContext->lpcReader; PCSCD::SharedReaderState *rs = PCSCD::SharedReaderState::overlay(rContext->readerState); DWORD tmpCardAtrLength = MAX_ATR_SIZE; rv = IFDStatusICC(rContext, &dwStatus, rs->xcardAtr(), &tmpCardAtrLength); secdebug("pcscd", "EHStatusHandlerThread: initial call to IFDStatusICC: %d [%04X]", rv, rv); if (dwStatus & SCARD_PRESENT) { tmpCardAtrLength = MAX_ATR_SIZE; rv = IFDPowerICC(rContext, IFD_POWER_UP, rs->xcardAtr(), &tmpCardAtrLength); /* the protocol is unset after a power on */ rs->xcardProtocol(SCARD_PROTOCOL_UNSET); secdebug("pcscd", "EHStatusHandlerThread: initial call to IFDPowerICC: %d [%04X]", rv, rv); if (rv == IFD_SUCCESS) { rs->xcardAtrLength(tmpCardAtrLength); dwStatus |= SCARD_PRESENT; dwStatus &= ~SCARD_ABSENT; dwStatus |= SCARD_POWERED; dwStatus |= SCARD_NEGOTIABLE; dwStatus &= ~SCARD_SPECIFIC; dwStatus &= ~SCARD_SWALLOWED; dwStatus &= ~SCARD_UNKNOWN; if (rs->xcardAtrLength() > 0) { LogXxd(PCSC_LOG_INFO, "Card ATR: ", rs->xcardAtr(), rs->xcardAtrLength()); } else Log1(PCSC_LOG_INFO, "Card ATR: (NULL)"); } else { dwStatus |= SCARD_PRESENT; dwStatus &= ~SCARD_ABSENT; dwStatus |= SCARD_SWALLOWED; dwStatus &= ~SCARD_POWERED; dwStatus &= ~SCARD_NEGOTIABLE; dwStatus &= ~SCARD_SPECIFIC; dwStatus &= ~SCARD_UNKNOWN; Log3(PCSC_LOG_ERROR, "Error powering up card: %d 0x%04X", rv, rv); } dwCurrentState = SCARD_PRESENT; } else { dwStatus |= SCARD_ABSENT; dwStatus &= ~SCARD_PRESENT; dwStatus &= ~SCARD_POWERED; dwStatus &= ~SCARD_NEGOTIABLE; dwStatus &= ~SCARD_SPECIFIC; dwStatus &= ~SCARD_SWALLOWED; dwStatus &= ~SCARD_UNKNOWN; rs->xcardAtrLength(0); rs->xcardProtocol(SCARD_PROTOCOL_UNSET); dwCurrentState = SCARD_ABSENT; } /* * Set all the public attributes to this reader */ rs->xreaderState(dwStatus); dwReaderSharing = rContext->dwContexts; rs->sharing(dwReaderSharing); SYS_MMapSynchronize((void *) rContext->readerState, pageSize); while (1) { dwStatus = 0; // Defensive measure if (!rContext->vHandle) { // Exit and notify the caller secdebug("pcscd", "EHStatusHandlerThread: lost dynamic callbacks ??"); ReaderContextUnlock(rContext); SYS_ThreadDetach(rContext->pthThread); SYS_ThreadExit(0); } DWORD tmpCardAtrLength = MAX_ATR_SIZE; rv = IFDStatusICC(rContext, &dwStatus, rs->xcardAtr(), &tmpCardAtrLength); if (rv != SCARD_S_SUCCESS) { Log2(PCSC_LOG_ERROR, "Error communicating to: %s", lpcReader); /* * Set error status on this reader while errors occur */ DWORD readerStateTmp = rs->xreaderState(); readerStateTmp &= ~SCARD_ABSENT; readerStateTmp &= ~SCARD_PRESENT; readerStateTmp &= ~SCARD_POWERED; readerStateTmp &= ~SCARD_NEGOTIABLE; readerStateTmp &= ~SCARD_SPECIFIC; readerStateTmp &= ~SCARD_SWALLOWED; readerStateTmp |= SCARD_UNKNOWN; rs->xcardAtrLength(0); rs->xcardProtocol(SCARD_PROTOCOL_UNSET); rs->xreaderState(readerStateTmp); dwCurrentState = SCARD_UNKNOWN; SYS_MMapSynchronize((void *) rContext->readerState, pageSize); /* * This code causes race conditions on G4's with USB * insertion */ /* * dwErrorCount += 1; SYS_Sleep(1); */ /* * After 10 seconds of errors, try to reinitialize the reader * This sometimes helps bring readers out of *crazy* states. */ /* * if ( dwErrorCount == 10 ) { RFUnInitializeReader( rContext * ); RFInitializeReader( rContext ); dwErrorCount = 0; } */ /* * End of race condition code block */ } if (dwStatus & SCARD_ABSENT) { if (dwCurrentState == SCARD_PRESENT || dwCurrentState == SCARD_UNKNOWN) { /* * Change the status structure */ Log2(PCSC_LOG_INFO, "Card Removed From %s", lpcReader); /* * Notify the card has been removed */ RFSetReaderEventState(rContext, SCARD_REMOVED); rs->xcardAtrLength(0); rs->xcardProtocol(SCARD_PROTOCOL_UNSET); DWORD readerStateTmp = rs->xreaderState(); readerStateTmp |= SCARD_ABSENT; readerStateTmp &= ~SCARD_UNKNOWN; readerStateTmp &= ~SCARD_PRESENT; readerStateTmp &= ~SCARD_POWERED; readerStateTmp &= ~SCARD_NEGOTIABLE; readerStateTmp &= ~SCARD_SWALLOWED; readerStateTmp &= ~SCARD_SPECIFIC; rs->xreaderState(readerStateTmp); dwCurrentState = SCARD_ABSENT; SYS_MMapSynchronize((void *) rContext->readerState, pageSize); } } else if (dwStatus & SCARD_PRESENT) { if (dwCurrentState == SCARD_ABSENT || dwCurrentState == SCARD_UNKNOWN) { /* * Power and reset the card */ SYS_USleep(PCSCLITE_STATUS_WAIT); DWORD tmpCardAtrLength = MAX_ATR_SIZE; rv = IFDPowerICC(rContext, IFD_POWER_UP, rs->xcardAtr(), &tmpCardAtrLength); /* the protocol is unset after a power on */ rs->xcardProtocol(SCARD_PROTOCOL_UNSET); secdebug("pcscd", "EHStatusHandlerThread: power-and-reset call to IFDPowerICC: %d [%04X]", rv, rv); DWORD readerStateTmp = rs->xreaderState(); if (rv == IFD_SUCCESS) { rs->xcardAtrLength(tmpCardAtrLength); readerStateTmp |= SCARD_PRESENT; readerStateTmp &= ~SCARD_ABSENT; readerStateTmp |= SCARD_POWERED; readerStateTmp |= SCARD_NEGOTIABLE; readerStateTmp &= ~SCARD_SPECIFIC; readerStateTmp &= ~SCARD_UNKNOWN; readerStateTmp &= ~SCARD_SWALLOWED; rs->xreaderState(readerStateTmp); /* * Notify the card has been reset */ RFSetReaderEventState(rContext, SCARD_RESET); } else { readerStateTmp |= SCARD_PRESENT; readerStateTmp &= ~SCARD_ABSENT; readerStateTmp |= SCARD_SWALLOWED; readerStateTmp &= ~SCARD_POWERED; readerStateTmp &= ~SCARD_NEGOTIABLE; readerStateTmp &= ~SCARD_SPECIFIC; readerStateTmp &= ~SCARD_UNKNOWN; rs->xreaderState(readerStateTmp); rs->xcardAtrLength(0); } dwCurrentState = SCARD_PRESENT; SYS_MMapSynchronize((void *) rContext->readerState, pageSize); Log2(PCSC_LOG_INFO, "Card inserted into %s", lpcReader); if (rv == IFD_SUCCESS) { if (rs->xcardAtrLength() > 0) LogXxd(PCSC_LOG_INFO, "Card ATR: ", rs->xcardAtr(), rs->xcardAtrLength()); else Log1(PCSC_LOG_INFO, "Card ATR: (NULL)"); } else Log1(PCSC_LOG_ERROR,"Error powering up card."); } } if (ReaderContextIsLocked(rContext)) { /* * Exit and notify the caller */ secdebug("pcscd", "EHStatusHandlerThread: parent requested shutdown"); ReaderContextUnlock(rContext); SYS_ThreadDetach(rContext->pthThread); SYS_ThreadExit(0); } /* * Sharing may change w/o an event pass it on */ if (dwReaderSharing != (uint32_t)rContext->dwContexts) { dwReaderSharing = rContext->dwContexts; rs->sharing(dwReaderSharing); SYS_MMapSynchronize((void *) rContext->readerState, pageSize); } SYS_USleep(PCSCLITE_STATUS_POLL_RATE); } }