Пример #1
0
static void OS_ThreadWrapper(void)
{
    /*  Execute the thread entry point  */
    current->entry_point(current->arg);

    /*  The thread is finished so we free all the TCB entries   */
    SYS_ThreadExit();
}
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);
	}
}