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

LONG SCardTransmit ( SCARDHANDLE  hCard,
LPCSCARD_IO_REQUEST  pioSendPci,
LPCBYTE  pbSendBuffer,
DWORD  cbSendLength,
LPSCARD_IO_REQUEST  pioRecvPci,
LPBYTE  pbRecvBuffer,
LPDWORD  pcbRecvLength 
)

This function sends an APDU to the smart card contained in the reader connected to by SCardConnect().

The card responds from the APDU and stores this response in pbRecvBuffer and it's length in SpcbRecvLength. SSendPci and SRecvPci are structures containing the following:

 typedef struct {
    DWORD dwProtocol;    // SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1
    DWORD cbPciLength;   // Length of this structure - not used
 } SCARD_IO_REQUEST;

Parameters:
[in] hCard Connection made from SCardConnect().
pioSendPci [inout] Structure of protocol information.
  • SCARD_PCI_T0 - Pre-defined T=0 PCI structure.
  • SCARD_PCI_T1 - Pre-defined T=1 PCI structure.
[in] pbSendBuffer APDU to send to the card.
[in] cbSendLength Length of the APDU.
pioRecvPci [inout] Structure of protocol information.
[out] pbRecvBuffer Response from the card.
pcbRecvLength [inout] Length of the response.
Returns:
Error code.
Return values:
SCARD_S_SUCCESS Successful.
SCARD_E_INVALID_HANDLE Invalid hCard handle.
SCARD_E_NOT_TRANSACTED APDU exchange not successful.
SCARD_E_PROTO_MISMATCH Connect protocol is different than desired.
SCARD_E_INVALID_VALUE Invalid Protocol, reader name, etc.
SCARD_E_READER_UNAVAILABLE The reader has been removed.
SCARD_W_RESET_CARD The card has been reset by another application.
SCARD_W_REMOVED_CARD The card has been removed from the reader.
Test:
 LONG rv;
 SCARDCONTEXT hContext;
 SCARDHANDLE hCard;
 DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
 SCARD_IO_REQUEST pioRecvPci;
 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);

Definition at line 1341 of file winscard.c.

References transmit_struct::cbSendLength, rxSharedSegment::data, transmit_struct::hCard, transmit_struct::pbSendBuffer, transmit_struct::pcbRecvLength, transmit_struct::pioRecvPci, transmit_struct::pioSendPci, _psContextMap::psChannelMap, psContextMap, _psChannelMap::readerName, SCARD_PROTOCOL_ANY_OLD, SCardCheckDaemonAvailability(), SCardLockThread(), SCardUnlockThread(), SHMClientRead(), SYS_MutexLock(), SYS_MutexUnLock(), and WrapSHMWrite().

Referenced by MSGFunctionDemarshall().

{
      LONG rv;
      PREADER_CONTEXT rContext = NULL;
      SCARD_IO_HEADER sSendPci, sRecvPci;
      DWORD dwRxLength, tempRxLength;

      if (pcbRecvLength == 0)
            return SCARD_E_INVALID_PARAMETER;

      dwRxLength = *pcbRecvLength;
      *pcbRecvLength = 0;

      if (hCard == 0)
            return SCARD_E_INVALID_HANDLE;

      if (pbSendBuffer == NULL || pbRecvBuffer == NULL || pioSendPci == NULL)
            return SCARD_E_INVALID_PARAMETER;

      /*
       * Must at least send a 4 bytes APDU
       */
      if (cbSendLength < 4)
            return SCARD_E_INVALID_PARAMETER;

      /*
       * Must at least have 2 status words even for SCardControl
       */
      if (dwRxLength < 2)
            return SCARD_E_INSUFFICIENT_BUFFER;

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

      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 some event has not occurred
       */
      if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
            return rv;

      /*
       * Check for some common errors
       */
      if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
      {
            if (rContext->readerState->readerState & SCARD_ABSENT)
            {
                  return SCARD_E_NO_SMARTCARD;
            }
      }

      if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
      {
            if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
            {
                  if (pioSendPci->dwProtocol != rContext->readerState->cardProtocol)
                  {
                        return SCARD_E_PROTO_MISMATCH;
                  }
            }
      }

      if (cbSendLength > MAX_BUFFER_SIZE)
      {
            return SCARD_E_INSUFFICIENT_BUFFER;
      }

      /*
       * Removed - a user may allocate a larger buffer if ( dwRxLength >
       * MAX_BUFFER_SIZE ) { return SCARD_E_INSUFFICIENT_BUFFER; }
       */

      /*
       * Quick fix: PC/SC starts at 1 for bit masking but the IFD_Handler
       * just wants 0 or 1
       */

      sSendPci.Protocol = 0; /* protocol T=0 by default */

      if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
      {
            sSendPci.Protocol = 1;
      } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
      {
            /*
             * This is temporary ......
             */
            sSendPci.Protocol = SCARD_PROTOCOL_RAW;
      } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
      {
        /* Fix by Amira (Athena) */
            unsigned long i;
            unsigned long prot = rContext->readerState->cardProtocol;

            for (i = 0 ; prot != 1 ; i++)
                  prot >>= 1;

            sSendPci.Protocol = i;
      }

      sSendPci.Length = pioSendPci->cbPciLength;

      /* the protocol number is decoded a few lines above */
      Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%d", sSendPci.Protocol);

      tempRxLength = dwRxLength;

      if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
      {
            rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
                  pbRecvBuffer, &dwRxLength);
      } else
      {
            rv = IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
                  cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
      }

      if (pioRecvPci)
      {
            pioRecvPci->dwProtocol = sRecvPci.Protocol;
            pioRecvPci->cbPciLength = sRecvPci.Length;
      }

      /*
       * Check for any errors that might have occurred
       */

      if (rv != SCARD_S_SUCCESS)
      {
            *pcbRecvLength = 0;
            Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
            return SCARD_E_NOT_TRANSACTED;
      }

      /*
       * Available is less than received
       */
      if (tempRxLength < dwRxLength)
      {
            *pcbRecvLength = 0;
            return SCARD_E_INSUFFICIENT_BUFFER;
      }

      if (dwRxLength > MAX_BUFFER_SIZE)
      {
            *pcbRecvLength = 0;
            return SCARD_E_INSUFFICIENT_BUFFER;
      }

      /*
       * Successful return
       */
      *pcbRecvLength = dwRxLength;
      return SCARD_S_SUCCESS;
}


Generated by  Doxygen 1.6.0   Back to index