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); } } }
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); } }