int main(/*@unused@*/ int argc, /*@unused@*/ char **argv) { SCARDHANDLE hCard; SCARDCONTEXT hContext; SCARD_READERSTATE rgReaderStates[1]; DWORD dwReaderLen, dwState, dwProt, dwAtrLen; DWORD dwPref, dwReaders = 0; char *pcReader = NULL, *mszReaders; #ifdef USE_AUTOALLOCATE unsigned char *pbAtr = NULL; #else unsigned char pbAtr[MAX_ATR_SIZE]; #endif union { unsigned char as_char[100]; DWORD as_DWORD; uint32_t as_uint32_t; } buf; DWORD dwBufLen; unsigned char *pbAttr = NULL; DWORD pcbAttrLen; char *mszGroups; DWORD dwGroups = 0; long rv; DWORD i; int p, iReader; int iList[16] = {0}; SCARD_IO_REQUEST ioRecvPci = *SCARD_PCI_T0; /* use a default value */ const SCARD_IO_REQUEST *pioSendPci; unsigned char bSendBuffer[MAX_BUFFER_SIZE]; unsigned char bRecvBuffer[MAX_BUFFER_SIZE]; DWORD send_length, length; (void)argc; (void)argv; printf("\nMUSCLE PC/SC Lite unitary test Program\n\n"); printf(MAGENTA "THIS 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" NORMAL); printf("Testing SCardEstablishContext\t: "); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); test_rv(rv, hContext, PANIC); printf("Testing SCardIsValidContext\t: "); rv = SCardIsValidContext(hContext); test_rv(rv, hContext, PANIC); printf("Testing SCardIsValidContext\t: "); rv = SCardIsValidContext(hContext+1); test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardListReaderGroups\t: "); #ifdef USE_AUTOALLOCATE dwGroups = SCARD_AUTOALLOCATE; rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups); #else rv = SCardListReaderGroups(hContext, NULL, &dwGroups); test_rv(rv, hContext, PANIC); printf("Testing SCardListReaderGroups\t: "); mszGroups = calloc(dwGroups, sizeof(char)); rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups); #endif test_rv(rv, hContext, PANIC); /* * Have to understand the multi-string here */ p = 0; for (i = 0; i+1 < dwGroups; i++) { ++p; printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]); while (mszGroups[++i] != 0) ; } #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, mszGroups); test_rv(rv, hContext, PANIC); #else free(mszGroups); #endif wait_for_card_again: mszGroups = NULL; printf("Testing SCardListReaders\t: "); rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders); test_rv(rv, hContext, DONT_PANIC); if (SCARD_E_NO_READERS_AVAILABLE == rv) { printf("Testing SCardGetStatusChange \n"); printf("Please insert a working reader\t: "); (void)fflush(stdout); rgReaderStates[0].szReader = "\\\\?PnP?\\Notification"; rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY; rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1); test_rv(rv, hContext, PANIC); } printf("Testing SCardListReaders\t: "); #ifdef USE_AUTOALLOCATE dwReaders = SCARD_AUTOALLOCATE; rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders); #else rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders); test_rv(rv, hContext, PANIC); printf("Testing SCardListReaders\t: "); mszReaders = calloc(dwReaders, sizeof(char)); rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders); #endif test_rv(rv, hContext, DONT_PANIC); /* * Have to understand the multi-string here */ p = 0; for (i = 0; i+1 < dwReaders; i++) { ++p; printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]); iList[p] = i; while (mszReaders[++i] != 0) ; } if (p > 1) do { char input[80]; char *r; printf("Enter the reader number\t\t: "); r = fgets(input, sizeof(input), stdin); if (NULL == r) iReader = -1; else iReader = atoi(input); if (iReader > p || iReader <= 0) printf("Invalid Value - try again\n"); } while (iReader > p || iReader <= 0); else iReader = 1; rgReaderStates[0].szReader = &mszReaders[iList[iReader]]; rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY; printf("Waiting for card insertion\t: "); (void)fflush(stdout); rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1); test_rv(rv, hContext, PANIC); if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN) { printf("\nA reader has been connected/disconnected\n"); goto wait_for_card_again; } printf("Testing SCardConnect\t\t: "); rv = SCardConnect(hContext, &mszReaders[iList[iReader]], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwPref); test_rv(rv, hContext, PANIC); switch(dwPref) { case SCARD_PROTOCOL_T0: pioSendPci = SCARD_PCI_T0; break; case SCARD_PROTOCOL_T1: pioSendPci = SCARD_PCI_T1; break; case SCARD_PROTOCOL_RAW: pioSendPci = SCARD_PCI_RAW; break; default: printf("Unknown protocol\n"); return -1; } /* APDU select file */ printf("Select file:"); send_length = 7; memcpy(bSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", send_length); for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit\t\t: "); rv = SCardTransmit(hCard, pioSendPci, bSendBuffer, send_length, &ioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf(" card response:" GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); printf("Testing SCardControl\t\t: "); #ifdef PCSC_PRE_120 { char buffer[1024] = "Foobar"; DWORD cbRecvLength = sizeof(buffer); rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength); } #else { char buffer[1024] = { 0x02 }; DWORD cbRecvLength = sizeof(buffer); rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer, sizeof(buffer), &cbRecvLength); if (cbRecvLength && (SCARD_S_SUCCESS == rv)) { for (i=0; i<cbRecvLength; i++) printf("%c", buffer[i]); printf(" "); } } #endif test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardGetAttrib\t\t: "); #ifdef USE_AUTOALLOCATE pcbAttrLen = SCARD_AUTOALLOCATE; rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr, &pcbAttrLen); #else rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen); pbAttr = malloc(pcbAttrLen); } printf("Testing SCardGetAttrib\t\t: "); rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen); #endif test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr); #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAttr); test_rv(rv, hContext, PANIC); #else if (pbAttr) free(pbAttr); #endif printf("Testing SCardGetAttrib\t\t: "); #ifdef USE_AUTOALLOCATE pcbAttrLen = SCARD_AUTOALLOCATE; rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr, &pcbAttrLen); #else rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen); pbAttr = malloc(pcbAttrLen); } printf("Testing SCardGetAttrib\t\t: "); rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen); #endif test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen); printf("SCARD_ATTR_ATR_STRING: " GREEN); for (i = 0; i < pcbAttrLen; i++) printf("%02X ", pbAttr[i]); printf("\n" NORMAL); } #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAttr); test_rv(rv, hContext, PANIC); #else if (pbAttr) free(pbAttr); #endif printf("Testing SCardGetAttrib\t\t: "); dwBufLen = sizeof(buf); rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { int valid = 1; /* valid value by default */ long value; printf("Vendor IFD version\t\t: "); if (dwBufLen == sizeof(DWORD)) value = buf.as_DWORD; else { if (dwBufLen == sizeof(uint32_t)) value = buf.as_uint32_t; else { printf(RED "Unsupported size\n" NORMAL); valid = 0; /* invalid value */ } } if (valid) { int M = (value & 0xFF000000) >> 24; /* Major */ int m = (value & 0x00FF0000) >> 16; /* Minor */ int b = (value & 0x0000FFFF); /* build */ printf(GREEN "%d.%d.%d\n" NORMAL, M, m, b); } }
void testrun ( SCARDHANDLE* p_hCard, SCARDCONTEXT *p_hContext, SCARD_IO_REQUEST *p_pioSendPci, unsigned char ucLogChannel) { SCARDHANDLE hCard = *p_hCard; SCARDCONTEXT hContext = *p_hContext; long rv; DWORD i; int p, iReader; int iList[16]; SCARD_IO_REQUEST pioRecvPci; SCARD_IO_REQUEST pioSendPci = *p_pioSendPci; unsigned char bSendBuffer[MAX_BUFFER_SIZE]; unsigned char bRecvBuffer[MAX_BUFFER_SIZE]; DWORD send_length, length; /* APDU select file */ printf("\n------------- Test Channel %d --------------------\n",ucLogChannel); printf("Select Applet\n"); send_length = 12; memcpy(bSendBuffer, "\x00\xA4\x04\x00\x07\xD2\x76\x00\x01\x18\x01\x01", send_length); bSendBuffer[0]|=ucLogChannel; for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit\t\t: "); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf(" card response:" GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); printf("\nCASE 1 APDU\n"); send_length = 5; memcpy(bSendBuffer, "\x00\x01\x00\x00\x00", send_length); bSendBuffer[0]|=ucLogChannel; for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit\t\t: "); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf(" card response:" GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); printf("\nCASE 2 APDU\n"); send_length = 5; memcpy(bSendBuffer, "\x00\x02\x00\x00\x10", send_length); bSendBuffer[0]|=ucLogChannel; for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit\t\t: "); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf(" card response:" GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); printf("\nCASE 3 APDU\n"); send_length = 21; memcpy(bSendBuffer, "\x00\x03\x00\x00\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", send_length); bSendBuffer[0]|=ucLogChannel; for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit\t\t: "); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf(" card response:" GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); printf("\nCASE 4 APDU\n"); send_length = 22; memcpy(bSendBuffer, "\x00\x04\x00\x00\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\00", send_length); for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit\t\t: "); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf(" card response:" GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); /* printf("\nLong APDU\n"); send_length = 259; //253 byte command data + 5 byte header + 1 byte Le bSendBuffer[0] = 0x00; bSendBuffer[1] = 0x04; bSendBuffer[2] = 0x00; bSendBuffer[3] = 0x00; bSendBuffer[4] = 0xFD; unsigned int iIndex = 0; for (iIndex=5;iIndex<send_length-1;++iIndex) { bSendBuffer[iIndex]=iIndex-5; } bSendBuffer[send_length-1] = 0x00; for (i=0; i<send_length; i++) printf(" %02X", bSendBuffer[i]); printf("\n"); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit\t\t: "); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf(" card response:" GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); */ }
int main(/*@unused@*/ int argc, /*@unused@*/ char **argv) { SCARDHANDLE hCard; SCARDCONTEXT hContext; SCARD_READERSTATE_A rgReaderStates[1]; DWORD dwReaderLen, dwState, dwProt, dwAtrLen; DWORD dwPref, dwReaders = 0; char *pcReaders = NULL, *mszReaders; #ifdef USE_AUTOALLOCATE unsigned char *pbAtr = NULL; #else unsigned char pbAtr[MAX_ATR_SIZE]; #endif union { unsigned char as_char[100]; DWORD as_DWORD; uint32_t as_uint32_t; } buf; DWORD dwBufLen; unsigned char *pbAttr = NULL; DWORD pcbAttrLen; char *mszGroups; DWORD dwGroups = 0; long rv; DWORD i; int p, iReader; int iList[16]; SCARD_IO_REQUEST pioRecvPci; SCARD_IO_REQUEST pioSendPci; unsigned char bSendBuffer[MAX_BUFFER_SIZE]; unsigned char bRecvBuffer[MAX_BUFFER_SIZE]; DWORD send_length, length; (void)argc; (void)argv; printf("\nMUSCLE PC/SC Lite unitary test Program\n\n"); printf(MAGENTA "THIS 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" NORMAL); printf("Testing SCardEstablishContext\t: "); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); test_rv(rv, hContext, PANIC); printf("Testing SCardIsValidContext\t: "); rv = SCardIsValidContext(hContext); test_rv(rv, hContext, PANIC); printf("Testing SCardIsValidContext\t: "); rv = SCardIsValidContext(hContext+1); test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardListReaderGroups\t: "); #ifdef USE_AUTOALLOCATE dwGroups = SCARD_AUTOALLOCATE; rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups); #else rv = SCardListReaderGroups(hContext, NULL, &dwGroups); test_rv(rv, hContext, PANIC); printf("Testing SCardListReaderGroups\t: "); mszGroups = calloc(dwGroups, sizeof(char)); rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups); #endif test_rv(rv, hContext, PANIC); /* * Have to understand the multi-string here */ p = 0; for (i = 0; i+1 < dwGroups; i++) { ++p; printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]); while (mszGroups[++i] != 0) ; } #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, mszGroups); test_rv(rv, hContext, PANIC); #else free(mszGroups); #endif wait_for_card_again: mszGroups = NULL; printf("Testing SCardListReaders\t: "); rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders); test_rv(rv, hContext, DONT_PANIC); if (SCARD_E_NO_READERS_AVAILABLE == rv) { printf("Testing SCardGetStatusChange \n"); printf("Please insert a working reader\t: "); (void)fflush(stdout); rgReaderStates[0].szReader = "\\\\?PnP?\\Notification"; rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY; rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1); test_rv(rv, hContext, PANIC); } printf("Testing SCardListReaders\t: "); #ifdef USE_AUTOALLOCATE dwReaders = SCARD_AUTOALLOCATE; rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders); #else rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders); test_rv(rv, hContext, PANIC); printf("Testing SCardListReaders\t: "); mszReaders = calloc(dwReaders, sizeof(char)); rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders); #endif test_rv(rv, hContext, DONT_PANIC); /* * Have to understand the multi-string here */ p = 0; for (i = 0; i+1 < dwReaders; i++) { ++p; printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]); iList[p] = i; while (mszReaders[++i] != 0) ; } if (p > 1) do { char input[80]; printf("Enter the reader number\t\t: "); (void)fgets(input, sizeof(input), stdin); (void)sscanf(input, "%d", &iReader); if (iReader > p || iReader <= 0) printf("Invalid Value - try again\n"); } while (iReader > p || iReader <= 0); else iReader = 1; rgReaderStates[0].szReader = &mszReaders[iList[iReader]]; rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY; printf("Waiting for card insertion\t: "); (void)fflush(stdout); rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1); test_rv(rv, hContext, PANIC); if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN) { printf("\nA reader has been connected/disconnected\n"); goto wait_for_card_again; } printf("Testing SCardConnect\t\t: "); rv = SCardConnect(hContext, &mszReaders[iList[iReader]], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwPref); test_rv(rv, hContext, PANIC); switch(dwPref) { case SCARD_PROTOCOL_T0: pioSendPci = *SCARD_PCI_T0; break; case SCARD_PROTOCOL_T1: pioSendPci = *SCARD_PCI_T1; break; case SCARD_PROTOCOL_RAW: pioSendPci = *SCARD_PCI_RAW; break; default: printf("Unknown protocol\n"); return -1; } int bBreak = 0; while (1) { char inputCommand[1024]; char inputAPDU[1024]; int inputAPDULen = sizeof(inputAPDU); printf("Enter APDU to send, (e.g. 00:A4:04:00:00)\n"); printf("Command APDU: "); (void)fgets(inputCommand, sizeof(inputCommand), stdin); int stringlen = strlen(inputCommand); if( inputCommand[stringlen-1] == '\n' ) { inputCommand[stringlen-1] = 0; } //remove newline int bError = sc_hex_to_bin(inputCommand, inputAPDU, &inputAPDULen); //printf("debug - value bError: %i\n",bError); if (bError) { printf("Error parsing input\n\n"); continue; } send_length = inputAPDULen; if (inputAPDULen == 0) { break; } printf("debug inputAPDULen: %i\n",inputAPDULen); memcpy(bSendBuffer, inputAPDU, send_length); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit:\n "); printf("-> "); for (i=0; i<send_length; i++) { printf(" %02X", bSendBuffer[i]); } printf("\n"); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf("<- " GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); } testrun(&hCard, &hContext, &pioSendPci, 0); testrun(&hCard, &hContext, &pioSendPci, 1); testrun(&hCard, &hContext, &pioSendPci, 2); testrun(&hCard, &hContext, &pioSendPci, 3); printf("Testing SCardControl\t\t: "); #ifdef PCSC_PRE_120 { char buffer[1024] = "Foobar"; DWORD cbRecvLength = sizeof(buffer); rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength); } #else { char buffer[1024] = { 0x02 }; DWORD cbRecvLength = sizeof(buffer); rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer, sizeof(buffer), &cbRecvLength); if (cbRecvLength && (SCARD_S_SUCCESS == rv)) { for (i=0; i<cbRecvLength; i++) printf("%c", buffer[i]); printf(" "); } } #endif test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardGetAttrib\t\t: "); #ifdef USE_AUTOALLOCATE pcbAttrLen = SCARD_AUTOALLOCATE; rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr, &pcbAttrLen); #else rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen); pbAttr = malloc(pcbAttrLen); } printf("Testing SCardGetAttrib\t\t: "); rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen); #endif test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr); #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAttr); test_rv(rv, hContext, PANIC); #else if (pbAttr) free(pbAttr); #endif printf("Testing SCardGetAttrib\t\t: "); #ifdef USE_AUTOALLOCATE pcbAttrLen = SCARD_AUTOALLOCATE; rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr, &pcbAttrLen); #else rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen); pbAttr = malloc(pcbAttrLen); } printf("Testing SCardGetAttrib\t\t: "); rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen); #endif test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen); printf("SCARD_ATTR_ATR_STRING: " GREEN); for (i = 0; i < pcbAttrLen; i++) printf("%02X ", pbAttr[i]); printf("\n" NORMAL); } #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAttr); test_rv(rv, hContext, PANIC); #else if (pbAttr) free(pbAttr); #endif printf("Testing SCardGetAttrib\t\t: "); dwBufLen = sizeof(buf); rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) printf("Vendor IFD version\t\t: " GREEN "0x%08lX\n" NORMAL, buf.as_DWORD); printf("Testing SCardGetAttrib\t\t: "); dwBufLen = sizeof(buf); rv = SCardGetAttrib(hCard, SCARD_ATTR_MAXINPUT, buf.as_char, &dwBufLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { if (dwBufLen == sizeof(uint32_t)) printf("Max message length\t\t: " GREEN "%d\n" NORMAL, buf.as_uint32_t); else printf(RED "Wrong size" NORMAL); } printf("Testing SCardGetAttrib\t\t: "); dwBufLen = sizeof(buf); rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, buf.as_char, &dwBufLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) printf("Vendor name\t\t\t: " GREEN "%s\n" NORMAL, buf.as_char); printf("Testing SCardSetAttrib\t\t: "); rv = SCardSetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPCBYTE)"", 1); test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardStatus\t\t: "); #ifdef USE_AUTOALLOCATE dwReaderLen = SCARD_AUTOALLOCATE; dwAtrLen = SCARD_AUTOALLOCATE; rv = SCardStatus(hCard, (LPSTR)&pcReaders, &dwReaderLen, &dwState, &dwProt, (LPBYTE)&pbAtr, &dwAtrLen); #else dwReaderLen = 100; pcReaders = malloc(sizeof(char) * 100); dwAtrLen = MAX_ATR_SIZE; rv = SCardStatus(hCard, pcReaders, &dwReaderLen, &dwState, &dwProt, pbAtr, &dwAtrLen); #endif test_rv(rv, hContext, PANIC); printf("Current Reader Name\t\t: " GREEN "%s\n" NORMAL, pcReaders); printf("Current Reader State\t\t: " GREEN "0x%.4lx\n" NORMAL, dwState); printf("Current Reader Protocol\t\t: T=" GREEN "%ld\n" NORMAL, dwProt - 1); printf("Current Reader ATR Size\t\t: " GREEN "%ld" NORMAL " bytes\n", dwAtrLen); printf("Current Reader ATR Value\t: " GREEN); for (i = 0; i < dwAtrLen; i++) { printf("%02X ", pbAtr[i]); } printf(NORMAL "\n"); #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pcReaders); test_rv(rv, hContext, PANIC); printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAtr); test_rv(rv, hContext, PANIC); #else if (pcReaders) free(pcReaders); #endif if (rv != SCARD_S_SUCCESS) { (void)SCardDisconnect(hCard, SCARD_RESET_CARD); (void)SCardReleaseContext(hContext); } printf("Press enter: "); (void)getchar(); printf("Testing SCardReconnect\t\t: "); rv = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_UNPOWER_CARD, &dwPref); test_rv(rv, hContext, PANIC); printf("Testing SCardDisconnect\t\t: "); rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD); test_rv(rv, hContext, PANIC); #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, mszReaders); test_rv(rv, hContext, PANIC); #else free(mszReaders); #endif printf("Testing SCardReleaseContext\t: "); rv = SCardReleaseContext(hContext); test_rv(rv, hContext, PANIC); printf("\n"); printf("PC/SC Test Completed Successfully !\n"); return 0; }
int main(int argc, char *argv[]) { int current_reader; LONG rv; SCARDCONTEXT hContext; SCARD_READERSTATE *rgReaderStates_t = NULL; SCARD_READERSTATE rgReaderStates[1]; DWORD dwReaders = 0, dwReadersOld; DWORD timeout; LPSTR mszReaders = NULL; char *ptr, **readers = NULL; int nbReaders, i; char atr[MAX_ATR_SIZE*3+1]; /* ATR in ASCII */ char atr_command[sizeof(atr)+sizeof(ATR_PARSER)+2+1]; int opt; int analyse_atr = TRUE; const char *blue = ""; const char *red = ""; const char *magenta = ""; const char *color_end = ""; int pnp = TRUE; printf("PC/SC device scanner\n"); printf("V " VERSION " (c) 2001-2011, Ludovic Rousseau <*****@*****.**>\n"); printf("Compiled with PC/SC lite version: " PCSCLITE_VERSION_NUMBER "\n"); while ((opt = getopt(argc, argv, "Vhn")) != EOF) { switch (opt) { case 'n': analyse_atr = FALSE; break; case 'V': /* the version number is printed by default */ return 1; break; case 'h': default: usage(); return 1; break; } } if (argc - optind != 0) { usage(); return 1; } /* check if terminal supports color */ { const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode" }; char *term; term = getenv("TERM"); if (term) { size_t j; /* for each known color terminal */ for (j = 0; j < sizeof(terms) / sizeof(terms[0]); j++) { /* we found a supported term? */ if (0 == strcmp(terms[j], term)) { blue = "\33[34m"; red = "\33[31m"; magenta = "\33[35m"; color_end = "\33[0m"; break; } } } } rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); test_rv("SCardEstablishContext", rv, hContext); rgReaderStates[0].szReader = "\\\\?PnP?\\Notification"; rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE; rv = SCardGetStatusChange(hContext, 0, rgReaderStates, 1); if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN) { timeout = TIMEOUT; printf("%sPlug'n play reader name not supported. Using polling every %ld ms.%s\n", magenta, timeout, color_end); pnp = FALSE; } else { timeout = INFINITE; printf("%sUsing reader plug'n play mechanism%s\n", magenta, color_end); } get_readers: /* free memory possibly allocated in a previous loop */ if (NULL != readers) { free(readers); readers = NULL; } if (NULL != rgReaderStates_t) { free(rgReaderStates_t); rgReaderStates_t = NULL; } /* 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 */ printf("%sScanning present readers...%s\n", red, color_end); rv = SCardListReaders(hContext, NULL, NULL, &dwReaders); if (rv != SCARD_E_NO_READERS_AVAILABLE) test_rv("SCardListReaders", rv, hContext); dwReadersOld = dwReaders; /* if non NULL we came back so free first */ if (mszReaders) { free(mszReaders); mszReaders = NULL; } mszReaders = malloc(sizeof(char)*dwReaders); if (mszReaders == NULL) { printf("malloc: not enough memory\n"); return 1; } *mszReaders = '\0'; rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders); /* 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 (SCARD_E_NO_READERS_AVAILABLE == rv || 0 == nbReaders) { printf("%sWaiting for the first reader...%s", red, color_end); fflush(stdout); if (pnp) { rgReaderStates[0].szReader = "\\\\?PnP?\\Notification"; rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE; rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1); test_rv("SCardGetStatusChange", rv, hContext); } else { rv = SCARD_S_SUCCESS; while ((SCARD_S_SUCCESS == rv) && (dwReaders == dwReadersOld)) { rv = SCardListReaders(hContext, NULL, NULL, &dwReaders); if (SCARD_E_NO_READERS_AVAILABLE == rv) rv = SCARD_S_SUCCESS; sleep(1); } } printf("found one\n"); goto get_readers; } else test_rv("SCardListReader", rv, hContext); /* allocate the readers table */ readers = calloc(nbReaders+1, sizeof(char *)); if (NULL == readers) { printf("Not enough memory for readers table\n"); return -1; } /* fill the readers table */ nbReaders = 0; ptr = mszReaders; while (*ptr != '\0') { printf("%s%d: %s%s\n", blue, nbReaders, ptr, color_end); readers[nbReaders] = ptr; ptr += strlen(ptr)+1; nbReaders++; } /* allocate the ReaderStates table */ rgReaderStates_t = calloc(nbReaders+1, sizeof(* rgReaderStates_t)); if (NULL == rgReaderStates_t) { printf("Not enough memory for readers states\n"); return -1; } /* Set the initial states to something we do not know * The loop below will include this state to the dwCurrentState */ for (i=0; i<nbReaders; i++) { rgReaderStates_t[i].szReader = readers[i]; rgReaderStates_t[i].dwCurrentState = SCARD_STATE_UNAWARE; rgReaderStates_t[i].cbAtr = sizeof rgReaderStates_t[i].rgbAtr; } rgReaderStates_t[nbReaders].szReader = "\\\\?PnP?\\Notification"; rgReaderStates_t[nbReaders].dwCurrentState = SCARD_STATE_UNAWARE; /* Wait endlessly for all events in the list of readers * We only stop in case of an error */ if (pnp) nbReaders++; rv = SCardGetStatusChange(hContext, timeout, rgReaderStates_t, nbReaders); while ((rv == SCARD_S_SUCCESS) || (rv == SCARD_E_TIMEOUT)) { time_t t; if (pnp) { if (rgReaderStates_t[nbReaders-1].dwEventState & SCARD_STATE_CHANGED) goto get_readers; } else { /* A new reader appeared? */ if ((SCardListReaders(hContext, NULL, NULL, &dwReaders) == SCARD_S_SUCCESS) && (dwReaders != dwReadersOld)) goto get_readers; } if (rv != SCARD_E_TIMEOUT) { /* Timestamp the event as we get notified */ t = time(NULL); printf("\n%s", ctime(&t)); } /* Now we have an event, check all the readers in the list to see what * happened */ for (current_reader=0; current_reader < nbReaders; current_reader++) { if (rgReaderStates_t[current_reader].dwEventState & SCARD_STATE_CHANGED) { /* If something has changed the new state is now the current * state */ rgReaderStates_t[current_reader].dwCurrentState = rgReaderStates_t[current_reader].dwEventState; } else /* If nothing changed then skip to the next reader */ continue; /* From here we know that the state for the current reader has * changed because we did not pass through the continue statement * above. */ /* Specify the current reader's number and name */ printf("Reader %d: %s%s%s\n", current_reader, magenta, rgReaderStates_t[current_reader].szReader, color_end); /* Dump the full current state */ printf(" Card state: %s", red); if (rgReaderStates_t[current_reader].dwEventState & SCARD_STATE_IGNORE) printf("Ignore this reader, "); if (rgReaderStates_t[current_reader].dwEventState & SCARD_STATE_UNKNOWN) { printf("Reader unknown\n"); goto get_readers; } if (rgReaderStates_t[current_reader].dwEventState & SCARD_STATE_UNAVAILABLE) printf("Status unavailable, "); if (rgReaderStates_t[current_reader].dwEventState & SCARD_STATE_EMPTY) printf("Card removed, "); if (rgReaderStates_t[current_reader].dwEventState & SCARD_STATE_PRESENT) printf("Card inserted, "); if (rgReaderStates_t[current_reader].dwEventState & SCARD_STATE_ATRMATCH) printf("ATR matches card, "); if (rgReaderStates_t[current_reader].dwEventState & SCARD_STATE_EXCLUSIVE) printf("Exclusive Mode, "); if (rgReaderStates_t[current_reader].dwEventState & SCARD_STATE_INUSE) printf("Shared Mode, "); if (rgReaderStates_t[current_reader].dwEventState & SCARD_STATE_MUTE) printf("Unresponsive card, "); printf("%s\n", color_end); /* force display */ fflush(stdout); /* Also dump the ATR if available */ if (rgReaderStates_t[current_reader].cbAtr > 0) { printf(" ATR: "); if (rgReaderStates_t[current_reader].cbAtr) { unsigned int j; for (j=0; j<rgReaderStates_t[current_reader].cbAtr; j++) sprintf(&atr[j*3], "%02X ", rgReaderStates_t[current_reader].rgbAtr[j]); atr[j*3-1] = '\0'; } else atr[0] = '\0'; printf("%s%s%s\n", magenta, atr, color_end); /* force display */ fflush(stdout); if (analyse_atr) { printf("\n"); sprintf(atr_command, ATR_PARSER " '%s'", atr); if (system(atr_command)) perror(atr_command); } } } /* for */ rv = SCardGetStatusChange(hContext, timeout, rgReaderStates_t, nbReaders); } /* while */ /* If we get out the loop, GetStatusChange() was unsuccessful */ test_rv("SCardGetStatusChange", rv, hContext); /* We try to leave things as clean as possible */ rv = SCardReleaseContext(hContext); test_rv("SCardReleaseContext", rv, hContext); /* free memory possibly allocated */ if (NULL != readers) free(readers); if (NULL != rgReaderStates_t) free(rgReaderStates_t); return 0; } /* main */