Logo Search packages:      
Sourcecode: pcsc-lite version File versions  Download package

PCSC_API LONG SCardReconnect ( SCARDHANDLE  hCard,
DWORD  dwShareMode,
DWORD  dwPreferredProtocols,
DWORD  dwInitialization,
LPDWORD  pdwActiveProtocol 
)

This function reestablishes a connection to a reader that was previously connected to using SCardConnect().

In a multi application environment it is possible for an application to reset the card in shared mode. When this occurs any other application trying to access certain commands will be returned the value SCARD_W_RESET_CARD. When this occurs SCardReconnect() must be called in order to acknowledge that the card was reset and allow it to change it's state accordingly.

Parameters:
[in] hCard Handle to a previous call to connect.
[in] dwShareMode Mode of connection type: exclusive/shared.
  • SCARD_SHARE_SHARED - This application will allow others to share the reader.
  • SCARD_SHARE_EXCLUSIVE - This application will NOT allow others to share the reader.
[in] dwPreferredProtocols Desired protocol use.
  • SCARD_PROTOCOL_T0 - Use the T=0 protocol.
  • SCARD_PROTOCOL_T1 - Use the T=1 protocol.
  • SCARD_PROTOCOL_RAW - Use with memory type cards.
dwPreferredProtocols is a bit mask of acceptable protocols for the connection. You can use (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if you do not have a preferred protocol.
[in] dwInitialization Desired action taken on the card/reader.
  • SCARD_LEAVE_CARD - Do nothing.
  • SCARD_RESET_CARD - Reset the card (warm reset).
  • SCARD_UNPOWER_CARD - Unpower the card (cold reset).
  • SCARD_EJECT_CARD - Eject the card.
[out] pdwActiveProtocol Established protocol to this connection.
Returns:
Error code.
Return values:
SCARD_S_SUCCESS Successful.
SCARD_E_INVALID_HANDLE Invalid hCard handle.
SCARD_E_NOT_READY Could not allocate the desired port.
SCARD_E_INVALID_VALUE Invalid sharing mode, requested protocol, or reader name.
SCARD_E_READER_UNAVAILABLE The reader has been removed.
SCARD_E_UNSUPPORTED_FEATURE Protocol not supported.
SCARD_E_SHARING_VIOLATION Someone else has exclusive rights.
Test:
 SCARDCONTEXT hContext;
 SCARDHANDLE hCard;
 DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
 LONG rv;
 BYTE pbRecvBuffer[10];
 BYTE pbSendBuffer[] = {0xC0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00};
 ...
 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
 rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
 ...
 dwSendLength = sizeof(pbSendBuffer);
 dwRecvLength = sizeof(pbRecvBuffer);
 rv = SCardTransmit(hCard, SCARD_PCI_T0, pbSendBuffer, dwSendLength, &pioRecvPci, pbRecvBuffer, &dwRecvLength);
 / * Card has been reset by another application * /
 if (rv == SCARD_W_RESET_CARD)
 {
   rv = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &dwActiveProtocol);
 }

Definition at line 393 of file winscard.c.

References rxSharedSegment::data, reconnect_struct::dwInitialization, reconnect_struct::dwPreferredProtocols, reconnect_struct::dwShareMode, reconnect_struct::hCard, MAX_ATR_SIZE, PCSCLITE_CLIENT_ATTEMPTS, PCSCLITE_MAX_READERS_CONTEXTS, PCSCLITE_STATUS_POLL_RATE, reconnect_struct::pdwActiveProtocol, _psContextMap::psChannelMap, psContextMap, _psChannelMap::readerName, SCARD_ABSENT, SCARD_EJECT_CARD, SCARD_EXCLUSIVE_CONTEXT, SCARD_LAST_CONTEXT, SCARD_LEAVE_CARD, SCARD_NEGOTIABLE, SCARD_POWERED, SCARD_PRESENT, SCARD_PROTOCOL_ANY_OLD, SCARD_PROTOCOL_RAW, SCARD_PROTOCOL_T0, SCARD_PROTOCOL_T1, SCARD_PROTOCOL_UNSET, SCARD_RESET, SCARD_RESET_CARD, SCARD_SHARE_DIRECT, SCARD_SHARE_EXCLUSIVE, SCARD_SHARE_SHARED, SCARD_SPECIFIC, SCARD_SWALLOWED, SCARD_UNKNOWN, SCARD_UNPOWER_CARD, SCardCheckDaemonAvailability(), SCardLockThread(), SCardUnlockThread(), SHMClientRead(), SYS_MutexLock(), SYS_MutexUnLock(), SYS_USleep(), and WrapSHMWrite().

Referenced by MSGFunctionDemarshall().

{
      LONG rv;
      PREADER_CONTEXT rContext = NULL;

      Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");

      if (hCard == 0)
            return SCARD_E_INVALID_HANDLE;

      /*
       * Handle the dwInitialization
       */
      if (dwInitialization != SCARD_LEAVE_CARD &&
                  dwInitialization != SCARD_RESET_CARD &&
                  dwInitialization != SCARD_UNPOWER_CARD)
            return SCARD_E_INVALID_VALUE;

      if (dwShareMode != SCARD_SHARE_SHARED &&
                  dwShareMode != SCARD_SHARE_EXCLUSIVE &&
                  dwShareMode != SCARD_SHARE_DIRECT)
            return SCARD_E_INVALID_VALUE;

      if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
                  !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
                  !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
                  !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
            return SCARD_E_PROTO_MISMATCH;

      if (pdwActiveProtocol == NULL)
            return SCARD_E_INVALID_PARAMETER;

      rv = RFReaderInfoById(hCard, &rContext);
      if (rv != SCARD_S_SUCCESS)
            return rv;

      /*
       * Make sure the reader is working properly
       */
      rv = RFCheckReaderStatus(rContext);
      if (rv != SCARD_S_SUCCESS)
            return rv;

      rv = RFFindReaderHandle(hCard);
      if (rv != SCARD_S_SUCCESS)
            return rv;

      /*
       * Make sure no one has a lock on this reader
       */
      if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
            return rv;

      /*
       * RFUnblockReader( rContext ); FIX - this doesn't work
       */

      if (dwInitialization == SCARD_RESET_CARD ||
            dwInitialization == SCARD_UNPOWER_CARD)
      {
            /*
             * Currently pcsc-lite keeps the card powered constantly
             */
            if (SCARD_RESET_CARD == dwInitialization)
                  rv = IFDPowerICC(rContext, IFD_RESET,
                        rContext->readerState->cardAtr,
                        &rContext->readerState->cardAtrLength);
            else
            {
                  rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
                        rContext->readerState->cardAtr,
                        &rContext->readerState->cardAtrLength);
                  rv = IFDPowerICC(rContext, IFD_POWER_UP,
                        rContext->readerState->cardAtr,
                        &rContext->readerState->cardAtrLength);
            }

            /* the protocol is unset after a power on */
            rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;

            /*
             * Notify the card has been reset
             * Not doing this could result in deadlock
             */
            rv = RFCheckReaderEventState(rContext, hCard);
            switch(rv)
            {
                  /* avoid deadlock */
                  case SCARD_W_RESET_CARD:
                        break;

                  case SCARD_W_REMOVED_CARD:
                        Log1(PCSC_LOG_ERROR, "card removed");
                        return SCARD_W_REMOVED_CARD;

                  /* invalid EventStatus */
                  case SCARD_E_INVALID_VALUE:
                        Log1(PCSC_LOG_ERROR, "invalid EventStatus");
                        return SCARD_F_INTERNAL_ERROR;

                  /* invalid hCard, but hCard was widely used some lines above :( */
                  case SCARD_E_INVALID_HANDLE:
                        Log1(PCSC_LOG_ERROR, "invalid handle");
                        return SCARD_F_INTERNAL_ERROR;

                  case SCARD_S_SUCCESS:
                        /*
                         * Notify the card has been reset
                         */
                        RFSetReaderEventState(rContext, SCARD_RESET);

                        /*
                         * Set up the status bit masks on dwStatus
                         */
                        if (rv == SCARD_S_SUCCESS)
                        {
                              rContext->readerState->readerState |= SCARD_PRESENT;
                              rContext->readerState->readerState &= ~SCARD_ABSENT;
                              rContext->readerState->readerState |= SCARD_POWERED;
                              rContext->readerState->readerState |= SCARD_NEGOTIABLE;
                              rContext->readerState->readerState &= ~SCARD_SPECIFIC;
                              rContext->readerState->readerState &= ~SCARD_SWALLOWED;
                              rContext->readerState->readerState &= ~SCARD_UNKNOWN;
                        }
                        else
                        {
                              rContext->readerState->readerState |= SCARD_PRESENT;
                              rContext->readerState->readerState &= ~SCARD_ABSENT;
                              rContext->readerState->readerState |= SCARD_SWALLOWED;
                              rContext->readerState->readerState &= ~SCARD_POWERED;
                              rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
                              rContext->readerState->readerState &= ~SCARD_SPECIFIC;
                              rContext->readerState->readerState &= ~SCARD_UNKNOWN;
                              rContext->readerState->cardAtrLength = 0;
                        }

                        if (rContext->readerState->cardAtrLength > 0)
                        {
                              Log1(PCSC_LOG_DEBUG, "Reset complete.");
                              LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
                                    rContext->readerState->cardAtr,
                                    rContext->readerState->cardAtrLength);
                        }
                        else
                        {
                              DWORD dwStatus, dwAtrLen;
                              UCHAR ucAtr[MAX_ATR_SIZE];

                              Log1(PCSC_LOG_ERROR, "Error resetting card.");
                              IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen);
                              if (dwStatus & SCARD_PRESENT)
                                    return SCARD_W_UNRESPONSIVE_CARD;
                              else
                                    return SCARD_E_NO_SMARTCARD;
                        }
                        break;

                  default:
                        Log2(PCSC_LOG_ERROR,
                              "invalid retcode from RFCheckReaderEventState (%X)", rv);
                        return SCARD_F_INTERNAL_ERROR;
                        break;
            }

      }
      else
            if (dwInitialization == SCARD_LEAVE_CARD)
            {
                  /*
                   * Do nothing
                   */
            }

      /*******************************************
       *
       * This section tries to decode the ATR
       * and set up which protocol to use
       *
       *******************************************/
      if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
            rContext->readerState->cardProtocol = SCARD_PROTOCOL_RAW;
      else
      {
            if (dwShareMode != SCARD_SHARE_DIRECT)
            {
                  /* the protocol is not yet set (no PPS yet) */
                  if (SCARD_PROTOCOL_UNSET == rContext->readerState->cardProtocol)
                  {
                        UCHAR ucAvailable, ucDefault;
                        int ret;

                        ucDefault = PHGetDefaultProtocol(rContext->readerState->cardAtr,
                              rContext->readerState->cardAtrLength);
                        ucAvailable =
                              PHGetAvailableProtocols(rContext->readerState->cardAtr,
                                          rContext->readerState->cardAtrLength);

                        /* If it is set to ANY let it do any of the protocols */
                        if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
                              dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;

                        ret = PHSetProtocol(rContext, dwPreferredProtocols,
                              ucAvailable, ucDefault);

                        /* keep cardProtocol = SCARD_PROTOCOL_UNSET in case of error  */
                        if (SET_PROTOCOL_PPS_FAILED == ret)
                              return SCARD_W_UNRESPONSIVE_CARD;

                        if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
                              return SCARD_E_PROTO_MISMATCH;

                        /* use negociated protocol */
                        rContext->readerState->cardProtocol = ret;
                  }
                  else
                  {
                        if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
                              return SCARD_E_PROTO_MISMATCH;
                  }
            }
      }

      *pdwActiveProtocol = rContext->readerState->cardProtocol;

      if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
      {
            if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
            {
                  /*
                   * Do nothing - we are already exclusive
                   */
            } else
            {
                  if (rContext->dwContexts == SCARD_LAST_CONTEXT)
                  {
                        rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
                        RFLockSharing(hCard);
                  } else
                  {
                        return SCARD_E_SHARING_VIOLATION;
                  }
            }
      } else if (dwShareMode == SCARD_SHARE_SHARED)
      {
            if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
            {
                  /*
                   * Do nothing - in sharing mode already
                   */
            } else
            {
                  /*
                   * We are in exclusive mode but want to share now
                   */
                  RFUnlockSharing(hCard);
                  rContext->dwContexts = SCARD_LAST_CONTEXT;
            }
      } else if (dwShareMode == SCARD_SHARE_DIRECT)
      {
            if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
            {
                  /*
                   * Do nothing - in sharing mode already
                   */
            } else
            {
                  /*
                   * We are in exclusive mode but want to share now
                   */
                  RFUnlockSharing(hCard);
                  rContext->dwContexts = SCARD_LAST_CONTEXT;
            }
      } else
            return SCARD_E_INVALID_VALUE;

      /*
       * Clear a previous event to the application
       */
      RFClearReaderEventState(rContext, hCard);

      /*
       * Allow the status thread to convey information
       */
      SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);

      return SCARD_S_SUCCESS;
}


Generated by  Doxygen 1.6.0   Back to index