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

pcsc_demo.c

/*
 * Sample program to use PC/SC API.
 *
 * MUSCLE SmartCard Development ( http://www.linuxnet.com )
 *
 * Copyright (C) 2003-2007
 *  Ludovic Rousseau <ludovic.rousseau@free.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * $Id: pcsc_demo.c 2594 2007-07-02 15:13:08Z rousseau $
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>

#include <PCSC/wintypes.h>
#include <PCSC/winscard.h>

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

/* PCSC error message pretty print */
#define PCSC_ERROR(rv, text) \
if (rv != SCARD_S_SUCCESS) \
{ \
      printf(text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
      goto end; \
} \
else \
{ \
      printf(text ": OK\n\n"); \
}

int main(int argc, char *argv[])
{
      LONG rv;
      SCARDCONTEXT hContext;
      DWORD dwReaders;
      LPSTR mszReaders = NULL;
      char *ptr, **readers = NULL;
      int nbReaders;
      SCARDHANDLE hCard;
      DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen;
      BYTE pbAtr[MAX_ATR_SIZE] = "";
      char pbReader[MAX_READERNAME] = "";
      int reader_nb;
      unsigned int i;
    SCARD_IO_REQUEST *pioSendPci;
      SCARD_IO_REQUEST pioRecvPci;
      BYTE pbRecvBuffer[10];
      BYTE pbSendBuffer[] = { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 };
      DWORD dwSendLength, dwRecvLength;

      printf("PC/SC sample code\n");
      printf("V 1.3 2003-2007, Ludovic Rousseau <ludovic.rousseau@free.fr>\n");

      printf("\nTHIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n");
      printf("Do NOT use it unless you really know what you do.\n\n");

      rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
      if (rv != SCARD_S_SUCCESS)
      {
            printf("SCardEstablishContext: Cannot Connect to Resource Manager %lX\n", rv);
            return EXIT_FAILURE;
      }

      /* Retrieve the available readers list.
       *
       * 1. Call with a null buffer to get the number of bytes to allocate
       * 2. malloc the necessary storage
       * 3. call with the real allocated buffer
       */
      rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
      PCSC_ERROR(rv, "SCardListReaders")

      mszReaders = malloc(sizeof(char)*dwReaders);
      if (mszReaders == NULL)
      {
            printf("malloc: not enough memory\n");
            goto end;
      }

      rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
      PCSC_ERROR(rv, "SCardListReaders")

      /* Extract readers from the null separated string and get the total
       * number of readers */
      nbReaders = 0;
      ptr = mszReaders;
      while (*ptr != '\0')
      {
            ptr += strlen(ptr)+1;
            nbReaders++;
      }

      if (nbReaders == 0)
      {
            printf("No reader found\n");
            goto end;
      }

      /* allocate the readers table */
      readers = calloc(nbReaders, sizeof(char *));
      if (NULL == readers)
      {
            printf("Not enough memory for readers[]\n");
            goto end;
      }

      /* fill the readers table */
      nbReaders = 0;
      ptr = mszReaders;
      while (*ptr != '\0')
      {
            printf("%d: %s\n", nbReaders, ptr);
            readers[nbReaders] = ptr;
            ptr += strlen(ptr)+1;
            nbReaders++;
      }

      if (argc > 1)
      {
            reader_nb = atoi(argv[1]);
            if (reader_nb < 0 || reader_nb >= nbReaders)
            {
                  printf("Wrong reader index: %d\n", reader_nb);
                  goto end;
            }
      }
      else
            reader_nb = 0;

      /* connect to a card */
      dwActiveProtocol = -1;
      rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED,
            SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
      printf(" Protocol: %ld\n", dwActiveProtocol);
      PCSC_ERROR(rv, "SCardConnect")

      /* get card status */
      dwAtrLen = sizeof(pbAtr);
      dwReaderLen = sizeof(pbReader);
      rv = SCardStatus(hCard, /*NULL*/ pbReader, &dwReaderLen, &dwState, &dwProt,
            pbAtr, &dwAtrLen);
      printf(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen);
      printf(" State: 0x%lX\n", dwState);
      printf(" Prot: %ld\n", dwProt);
      printf(" ATR (length %ld bytes):", dwAtrLen);
      for (i=0; i<dwAtrLen; i++)
            printf(" %02X", pbAtr[i]);
      printf("\n");
      PCSC_ERROR(rv, "SCardStatus")

    switch(dwActiveProtocol)
    {
        case SCARD_PROTOCOL_T0:
            pioSendPci = SCARD_PCI_T0;
            break;
        case SCARD_PROTOCOL_T1:
            pioSendPci = SCARD_PCI_T1;
            break;
        default:
            printf("Unknown protocol\n");
            return -1;
    }

      /* exchange APDU */
      dwSendLength = sizeof(pbSendBuffer);
      dwRecvLength = sizeof(pbRecvBuffer);
      printf("Sending: ");
      for (i=0; i<dwSendLength; i++)
            printf("%02X ", pbSendBuffer[i]);
      printf("\n");
      rv = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength,
            &pioRecvPci, pbRecvBuffer, &dwRecvLength);
      printf("Received: ");
      for (i=0; i<dwRecvLength; i++)
            printf("%02X ", pbRecvBuffer[i]);
      printf("\n");
      PCSC_ERROR(rv, "SCardTransmit")

      /* card disconnect */
      rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
      PCSC_ERROR(rv, "SCardDisconnect")

      /* connect to a card */
      dwActiveProtocol = -1;
      rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED,
            SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
      printf(" Protocol: %ld\n", dwActiveProtocol);
      PCSC_ERROR(rv, "SCardConnect")

      /* exchange APDU */
      dwSendLength = sizeof(pbSendBuffer);
      dwRecvLength = sizeof(pbRecvBuffer);
      printf("Sending: ");
      for (i=0; i<dwSendLength; i++)
            printf("%02X ", pbSendBuffer[i]);
      printf("\n");
      rv = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength,
            &pioRecvPci, pbRecvBuffer, &dwRecvLength);
      printf("Received: ");
      for (i=0; i<dwRecvLength; i++)
            printf("%02X ", pbRecvBuffer[i]);
      printf("\n");
      PCSC_ERROR(rv, "SCardTransmit")

      /* card reconnect */
      rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
            SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD,
            &dwActiveProtocol);
      PCSC_ERROR(rv, "SCardReconnect")

      /* get card status */
      dwAtrLen = sizeof(pbAtr);
      dwReaderLen = sizeof(pbReader);
      rv = SCardStatus(hCard, /*NULL*/ pbReader, &dwReaderLen, &dwState, &dwProt,
            pbAtr, &dwAtrLen);
      printf(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen);
      printf(" State: 0x%lX\n", dwState);
      printf(" Prot: %ld\n", dwProt);
      printf(" ATR (length %ld bytes):", dwAtrLen);
      for (i=0; i<dwAtrLen; i++)
            printf(" %02X", pbAtr[i]);
      printf("\n");
      PCSC_ERROR(rv, "SCardStatus")

      /* get card status change */
      {
            /* check only one reader */
            SCARD_READERSTATE_A rgReaderStates[1];

            rgReaderStates[0].szReader = pbReader;
            rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;

            rv = SCardGetStatusChange(hContext, 0, rgReaderStates, 1);
            printf(" state: 0x%04lX\n", rgReaderStates[0].dwEventState);
            PCSC_ERROR(rv, "SCardGetStatusChange")
      }

      /* begin transaction */
      rv = SCardBeginTransaction(hCard);
      PCSC_ERROR(rv, "SCardBeginTransaction")

      /* exchange APDU */
      dwSendLength = sizeof(pbSendBuffer);
      dwRecvLength = sizeof(pbRecvBuffer);
      printf("Sending: ");
      for (i=0; i<dwSendLength; i++)
            printf("%02X ", pbSendBuffer[i]);
      printf("\n");
      rv = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength,
            &pioRecvPci, pbRecvBuffer, &dwRecvLength);
      printf("Received: ");
      for (i=0; i<dwRecvLength; i++)
            printf("%02X ", pbRecvBuffer[i]);
      printf("\n");
      PCSC_ERROR(rv, "SCardTransmit")

      /* end transaction */
      rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
      PCSC_ERROR(rv, "SCardEndTransaction")

      /* card disconnect */
      rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
      PCSC_ERROR(rv, "SCardDisconnect")

end:
      /* We try to leave things as clean as possible */
      rv = SCardReleaseContext(hContext);
      if (rv != SCARD_S_SUCCESS)
            printf("SCardReleaseContext: %s (0x%lX)\n", pcsc_stringify_error(rv),
                  rv);

      /* free allocated memory */
      if (mszReaders)
            free(mszReaders);
      if (readers)
            free(readers);

      return EXIT_SUCCESS;
} /* main */


Generated by  Doxygen 1.6.0   Back to index