void testGetATR_3(SCARDCONTEXT* phContext, WCHAR* readerName) { DWORD retval; ULONG ulTimeout = INFINITE; ULONG ulReaderCount = 1; SCARD_READERSTATEW txreaderStates[1]; memset(txreaderStates,0, sizeof(txreaderStates)); txreaderStates[0].szReader = readerName; //get initial values retval = SCardGetStatusChange(*phContext, 0, txreaderStates ,ulReaderCount); //wait for changes txreaderStates[0].dwCurrentState = txreaderStates[0].dwEventState; retval = SCardGetStatusChange(*phContext, ulTimeout, txreaderStates ,ulReaderCount); printf ("trying to get the card's ATR by calling SCardGetStatusChange\n"); printf ("returned: ATR length = %d retval: 0x%08x\n",txreaderStates[0].cbAtr, retval); printf ("ATR = "); for(int i = 0; i < txreaderStates[0].cbAtr ; i++) { printf(" 0x%02x",txreaderStates[0].rgbAtr[i]); } printf ("\n"); }
testA(int argc,char** argv ) { int i; myprintf("=============================\n"); myprintf("Part A: Checking card monitor\n"); myprintf("=============================\n"); (rgReaderStates[0])->dwCurrentState = SCARD_STATE_UNAWARE; rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); if( (rgReaderStates[0])->dwEventState & SCARD_STATE_PRESENT ) { myprintf("<< Please remove smart card \n"); (rgReaderStates[0])->dwCurrentState = SCARD_STATE_PRESENT; rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); } printit("1.Please insert smart card"); (rgReaderStates[0])->dwCurrentState = SCARD_STATE_EMPTY; rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); myprintf("Passed\n"); printit("2. IOCTL_SMARTCARD_IS_PRESENT"); myprintf("Passed\n"); printit("3. Please remove smart card "); (rgReaderStates[0])->dwCurrentState = SCARD_STATE_PRESENT; rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); if( rv != SCARD_S_SUCCESS ) return -1; if( (rgReaderStates[0])->dwEventState & SCARD_STATE_EMPTY) myprintf("Passed\n"); else myprintf("Failed \n"); printit("4. IOCTL_SMARTCARD_IS_ABSENT"); myprintf("Passed\n"); printit("5. Insert and remove a smart card repeatedly"); (rgReaderStates[0])->dwCurrentState = SCARD_STATE_EMPTY; for(i=0;i<10;i++) { rv =SCardGetStatusChange( hContext, INFINITE, rgReaderStates[0], 1 ); (rgReaderStates[0])->dwCurrentState = (rgReaderStates[0])->dwEventState; } myprintf("Passed \n"); if( more_details ) { rv = SCardConnect(hContext, readerName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0| SCARD_PROTOCOL_T1, &hCard, &dwPref); if ( rv != SCARD_S_SUCCESS ) { SCardReleaseContext( hContext ); return 0; } readerlen=100; rv = SCardStatus(hCard,readerName,&readerlen,&readerstate,&protocol,r,&atrlen); if( rv != SCARD_S_SUCCESS ) { return -1; } myprintf("ATR :"); for(i=0;i<atrlen;i++) { myprintf("%0x ",r[i]); } myprintf("\n"); myprintf("Powered up successfully \n"); } return 0; }
bool QPCSCReaderPrivate::updateState() { if( !d->context ) return false; LONG err = SCardGetStatusChange( d->context, 0, &state, 1 ); return err == SCARD_S_SUCCESS; }
LC_CLIENT_RESULT LC_Client_Start(LC_CLIENT *cl) { LONG rv; assert(cl); #if 0 /* check whether pnp pseudo reader is available */ cl->readerStates[0].szReader = "\\\\?PnP?\\Notification"; cl->readerStates[0].dwCurrentState = SCARD_STATE_UNAWARE; rv=SCardGetStatusChange(cl->scardContext, 0, cl->readerStates, 1); if (cl->readerStates[0].dwEventState && SCARD_STATE_UNKNOWN) { DBG_INFO(LC_LOGDOMAIN, "PnP not supported"); cl->pnpAvailable=0; } else cl->pnpAvailable=1; #endif rv=LC_Client_UpdateReaderStates(cl); if (rv<0) { DBG_INFO(LC_LOGDOMAIN, "here (%d)", (int) rv); return LC_Client_ResultGeneric; } cl->lastUsedReader=-1; return LC_Client_ResultOk; }
/* -------------------------------------------------------------------------- */ LONG sc_init_u (sc_context *ctx, char *rdr) /* *rdr must be a full name */ { SCARD_READERSTATE rSt = {0}; LONG rc=SCARD_S_SUCCESS; DWORD dw=SCARD_AUTOALLOCATE; rc=SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx->hCtx); if (rc == SCARD_S_SUCCESS) { rSt.szReader = rdr; rSt.dwCurrentState = SCARD_STATE_UNAWARE; rc = SCardGetStatusChange(ctx->hCtx, 0, &rSt, 1); if ( (rSt.dwEventState & SCARD_STATE_EMPTY) > 0 ) rc = SC_BAD; else { ctx->rdr = NULL; ctx->rdrsz = SCARD_AUTOALLOCATE; ctx->CLA = 0; ctx->proto = SCARD_PCI_T0; ctx->rw = 0; rc = SCardConnect(ctx->hCtx, rdr, SCARD_SHARE_SHARED, SCARD_MYPROTOSET, &ctx->hCard, &dw); if (rc == SCARD_S_SUCCESS) { SCardGetAttrib(ctx->hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (LPBYTE)&ctx->rdr, &ctx->rdrsz); if (dw == SCARD_PROTOCOL_T1) ctx->proto = SCARD_PCI_T1; else if (dw == SCARD_PROTOCOL_RAW) ctx->proto = SCARD_PCI_RAW; } } if ( rc != SCARD_S_SUCCESS) SCardReleaseContext(ctx->hCtx); } return rc; } /* sc_init */
//PCSCREADERDRIVERDLL_API unsigned short CCONV HD_ProbeCard(HANDLE ContextNo, HANDLE devNo, short ivPortNo, short ivCardSeat) //PCSCREADERDRIVERDLL_API unsigned short CCONV HD_ProbeCard(HANDLE ContextNo, short ivPortNo, short ivCardSeat) PCSCREADERDRIVERDLL_API unsigned short CCONV HD_ProbeCard(HANDLE devNo,short ivCardSeat) { SCARDCONTEXT ContextNo=NULL; ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &ContextNo); if (ret != SCARD_S_SUCCESS) { // GetErrorCode(ret); return CER_PCSC_SCardEstablishContext ; } SCARD_READERSTATE udtReaderState[2]; DWORD EventStatetpm; char Reader[300]; strcpy(Reader,"Gemplus GemPC430 0\0"); udtReaderState[0].szReader=Reader; //udtReaderState[0].dwCurrentState = SCARD_STATE_UNAVAILABLE; //udtReaderState[0].dwCurrentState = SCARD_STATE_PRESENT; udtReaderState[0].dwCurrentState = SCARD_STATE_UNAWARE; // udtReaderState[0].dwEventState = SCARD_STATE_UNKNOWN |SCARD_STATE_CHANGED|SCARD_STATE_IGNORE; // udtReaderState[0].dwEventState = SCARD_STATE_PRESENT; // udtReaderState[0].dwEventState = SCARD_STATE_EMPTY; ret = SCardGetStatusChange(ContextNo, 0, udtReaderState, 1); if (ret != SCARD_S_SUCCESS) { // GetErrorCode(ret); // EventStatetpm = udtReaderState[0].dwEventState; // WriteLog("SCardGetStatusChange1", ivPortNo,EventStatetpm); SCardReleaseContext(ContextNo); ContextHandle = NULL; return CER_PCSC_SCardGetStatusChange; } EventStatetpm = udtReaderState[0].dwEventState; if ((EventStatetpm & 0x00000010)==0x00000010) //0x00000010 -->SCARD_STATE_EMPTY { // GetErrorCode(ret); SCardReleaseContext(ContextNo); ContextHandle = NULL; return CER_NOCARD; } ret = SCardReleaseContext(ContextNo); if (ret != SCARD_S_SUCCESS) { GetErrorCode(ret); return CER_PCSC_SCardReleaseContext; } ContextNo = NULL; return EXCUTE_SUC; }
long MySCardGetStatusChange( SCARDCONTEXT hContext, DWORD dwTimeout, LPSCARD_READERSTATE rgReaderStates, DWORD cReaders) { long result; DWORD timecnt; DWORD timeslot; timecnt = 0; #ifdef LINUX_OS fflush(stdout); #endif if(dwTimeout > 100) timeslot = 100; else timeslot = 1; do { result = SCardGetStatusChange(hContext, dwTimeout, rgReaderStates, cReaders); if(result != SCARD_S_SUCCESS) { PRINTERR(("SCardGetStatusChange Fail : %08X\n", result)); return result; } if(((rgReaderStates->dwCurrentState & SCARD_STATE_PRESENT) && !(rgReaderStates->dwEventState & SCARD_STATE_PRESENT)) || (!(rgReaderStates->dwCurrentState & SCARD_STATE_PRESENT) && (rgReaderStates->dwEventState & SCARD_STATE_PRESENT)) ) { break; } else { if(dwTimeout) { Sleep(timeslot); timecnt += timeslot; } } } while(timecnt < dwTimeout || dwTimeout == INFINITE); return result; }
/* -------------------------------------------------------------------------- */ LONG sc_init (sc_context *ctx, char *rdr) { SCARD_READERSTATE rSt = {0}; LONG rc=SCARD_S_SUCCESS; LPTSTR c=NULL, cc=NULL; DWORD dw=SCARD_AUTOALLOCATE; rc=SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx->hCtx); if (rc==SCARD_S_SUCCESS) { rc=SCardListReaders(ctx->hCtx, NULL, (LPTSTR) &c, &dw); if (rc==SCARD_S_SUCCESS) { cc=findfirststr(c, rdr); if (cc!=NULL) { rSt.szReader = cc; rSt.dwCurrentState = SCARD_STATE_UNAWARE; rc = SCardGetStatusChange(ctx->hCtx, 0, &rSt, 1); if ( (rSt.dwEventState & SCARD_STATE_EMPTY) > 0 ) rc = SC_BAD; else { ctx->rdr = NULL; ctx->rdrsz = SCARD_AUTOALLOCATE; ctx->CLA = 0; ctx->proto = SCARD_PCI_T0; ctx->rw = 0; rc=SCardConnect(ctx->hCtx, cc, SCARD_SHARE_SHARED, SCARD_MYPROTOSET, &ctx->hCard, &dw); if (dw==SCARD_PROTOCOL_T1) ctx->proto=SCARD_PCI_T1; else if (dw==SCARD_PROTOCOL_RAW) ctx->proto=SCARD_PCI_RAW; if (rc==SCARD_S_SUCCESS) SCardGetAttrib(ctx->hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (LPBYTE)&ctx->rdr, &ctx->rdrsz); } } else rc=SC_BAD; SCardFreeMemory(ctx->hCtx, c); } if ( rc != SCARD_S_SUCCESS) SCardReleaseContext(ctx->hCtx); } return rc; } /* sc_init */
void PCSC::WaitCard(){ ReaderState.szReader = nameCardreader; // récupération du nom du lecteur ReaderState.dwCurrentState = SCARD_STATE_UNAWARE; ReaderState.dwEventState = SCARD_STATE_UNAWARE; cout << "Carte en attente.." << endl; do{ //on recupere le Status du reader *ReturnValue = SCardGetStatusChange( Context, 30, &ReaderState, 1); }while((ReaderState.dwEventState & SCARD_STATE_PRESENT) == 0); // Tant que dwEventState & SCARD_STATE_PRESENT ne sont pas egale a 0 on continue la boucle cout << "Carte présente." <<endl ; }
DWORD WINAPI CReaderMonitor::ReaderMonitorProc(void* param) { HRESULT hRes; LPTSTR mszNewReaderNames = NULL; while (!InterlockedCompareExchange(&g_fExit,0,0)) { if (g_hContext == 0) { // trying to establish context hRes = SCardEstablishContext(g_dwScope, NULL, NULL, &g_hContext); if (hRes != SCARD_S_SUCCESS) { Sleep(POLL_PERIOD); if(InterlockedCompareExchange(&g_fExit,1,1)) break; g_hContext = 0; } } if (g_hContext) { if (SCARD_S_SUCCESS == SCardIsValidContext(g_hContext)) { // rescan reader list... mszNewReaderNames = NULL; DWORD cchReaderNames = 0; do { hRes = SCardListReaders(g_hContext, NULL, NULL, &cchReaderNames); if ((hRes == SCARD_S_SUCCESS) && cchReaderNames) { mszNewReaderNames = new TCHAR[cchReaderNames]; hRes = SCardListReaders(g_hContext, NULL, mszNewReaderNames, &cchReaderNames); if (hRes != SCARD_S_SUCCESS) { delete[] mszNewReaderNames; mszNewReaderNames = NULL; } } } while (hRes == SCARD_E_INSUFFICIENT_BUFFER); } else hRes = SCARD_E_NO_SERVICE; if(InterlockedCompareExchange(&g_fExit,1,1)) break; // check reader listing status DWORD cNewReaderStates = 0; SCARD_READERSTATE *pNewReaderStates = NULL; switch (hRes) { case ERROR_INVALID_HANDLE: case SCARD_E_INVALID_HANDLE: case SCARD_E_NO_SERVICE: case SCARD_E_SERVICE_STOPPED: SCardReleaseContext(g_hContext); g_hContext = 0; hRes = SCARD_S_SUCCESS; break; case SCARD_E_NO_READERS_AVAILABLE: hRes = SCARD_S_SUCCESS; break; case SCARD_S_SUCCESS: for (LPCTSTR pReader = mszNewReaderNames; *pReader != 0; pReader += _tcslen(pReader) + 1) cNewReaderStates++; if (cNewReaderStates) { pNewReaderStates = new SCARD_READERSTATE[cNewReaderStates]; memset(pNewReaderStates,0,cNewReaderStates* sizeof(SCARD_READERSTATE)); } default: break; } if(InterlockedCompareExchange(&g_fExit,1,1)) break; if (hRes == SCARD_S_SUCCESS) { // compare readers DWORD j; for (j = 0; j < g_cReaderStates; j++) g_pReaderStates[j].pvUserData = (LPVOID)1; LPCTSTR pReader = mszNewReaderNames; DWORD i = 0; if (pReader) { while (*pReader != 0) { pNewReaderStates[i].pvUserData = (LPVOID)1; pNewReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE; for (j = 0; j < g_cReaderStates; j++) { if (_tcscmp(pReader, g_pReaderStates[j].szReader) == 0) { g_pReaderStates[j].pvUserData = NULL; pNewReaderStates[i] = g_pReaderStates[j]; break; } } pNewReaderStates[i].szReader = pReader; pReader += _tcslen(pReader) + 1; i++; } } // check removed readers for (j = 0; j < g_cReaderStates; j++) { if (g_pReaderStates[j].pvUserData != NULL) { NotifyReaderUnplug(g_pReaderStates[j].szReader); if(InterlockedCompareExchange(&g_fExit,1,1)) goto end_label; } } // update current list if (g_pReaderStates) delete[] g_pReaderStates; if (g_mszReaderNames) delete[] g_mszReaderNames; g_mszReaderNames = mszNewReaderNames; g_pReaderStates = pNewReaderStates; g_cReaderStates = cNewReaderStates; mszNewReaderNames = NULL; } // check reader states if (g_cReaderStates == 0) { if (!g_bReadersListInitialized) { SetEvent(g_readersCheckedEvent); g_bReadersListInitialized = true; } Sleep(POLL_PERIOD); if(InterlockedCompareExchange(&g_fExit,1,1)) break; } else { hRes = SCardGetStatusChange(g_hContext, POLL_PERIOD, g_pReaderStates, g_cReaderStates); if(InterlockedCompareExchange(&g_fExit,1,1)) break; if (hRes == SCARD_S_SUCCESS) { // check changed readers... for (DWORD i = 0; i < g_cReaderStates && !InterlockedCompareExchange(&g_fExit,0,0); i++) { if (g_pReaderStates[i].pvUserData != NULL) { // new reader g_pReaderStates[i].pvUserData = NULL; g_pReaderStates[i].dwEventState &= ~SCARD_STATE_CHANGED; g_pReaderStates[i].dwCurrentState = g_pReaderStates[i].dwEventState; if ((g_pReaderStates[i].dwEventState & (SCARD_STATE_IGNORE | SCARD_STATE_MUTE)) == 0) NotifyReaderPlug(g_pReaderStates[i]); if(InterlockedCompareExchange(&g_fExit,1,1)) goto end_label; } else if (g_pReaderStates[i].dwEventState & SCARD_STATE_CHANGED) { // existing reader g_pReaderStates[i].dwEventState &= ~SCARD_STATE_CHANGED; if ( ((g_pReaderStates[i].dwEventState & (SCARD_STATE_IGNORE | SCARD_STATE_MUTE)) == 0) && ((g_pReaderStates[i].dwCurrentState & SCARD_STATE_MUTE) == 0) && ( ((g_pReaderStates[i].dwCurrentState & SCARD_STATE_PRESENT) && (!(g_pReaderStates[i].dwEventState & SCARD_STATE_PRESENT))) ||((!(g_pReaderStates[i].dwCurrentState & SCARD_STATE_PRESENT)) && (g_pReaderStates[i].dwEventState & SCARD_STATE_PRESENT)) ) ) { NotifyReaderChange(g_pReaderStates[i]); } g_pReaderStates[i].dwCurrentState = g_pReaderStates[i].dwEventState & (~(SCARD_STATE_CHANGED | SCARD_STATE_IGNORE)); if(InterlockedCompareExchange(&g_fExit,1,1)) goto end_label; } } } else if (hRes != SCARD_E_TIMEOUT) { if(InterlockedCompareExchange(&g_fExit,1,1)) goto end_label; // something strange happened. Act as if all readers where disconnected for (DWORD i = 0; i < g_cReaderStates; i++) { NotifyReaderUnplug(g_pReaderStates[i].szReader); if(InterlockedCompareExchange(&g_fExit,1,1)) goto end_label; } if (g_pReaderStates) delete[] g_pReaderStates; if (g_mszReaderNames) delete[] g_mszReaderNames; g_mszReaderNames = NULL; g_pReaderStates = NULL; g_cReaderStates = 0; SCardReleaseContext(g_hContext); g_hContext = 0; } if (!g_bReadersListInitialized) { SetEvent(g_readersCheckedEvent); g_bReadersListInitialized = true; } } } } end_label: ResetGlobals(); if(mszNewReaderNames) delete [] mszNewReaderNames; return 0; }
int main(int argc, char **argv) { SCARDCONTEXT hContext; SCARD_READERSTATE rgscState[MAXIMUM_SMARTCARD_READERS]; DWORD dwReaders, dwReadersOld = 0; LPSTR szReaders = NULL; DWORD dwReadersSz; BOOL first_run = TRUE; DWORD i, j; LONG rc; if ((argc >= 2) && (!strcmp(argv[1], "-m"))) gbChangeMasterKey = TRUE; /* * Welcome message, check parameters * --------------------------------- */ printf("SpringCard SDK for PC/SC (CSB6 family)\n"); printf("\n"); printf("NXP DESFIRE EV0 reference demo\n"); printf("------------------------------\n"); printf("www.springcard.com\n\n"); printf("\n"); printf("Press <Ctrl+C> to exit\n\n"); /* * Get a handle to the PC/SC resource manager * ------------------------------------------ */ rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); if(rc != SCARD_S_SUCCESS) { printf("SCardEstablishContext :%08lX\n",rc); return EXIT_FAILURE; } /* * Infinite loop, we'll exit only when killed by Ctrl+C * ---------------------------------------------------- */ for (;;) { /* * Get the list of available readers */ dwReadersSz = SCARD_AUTOALLOCATE; rc = SCardListReaders(hContext, NULL, /* Any group */ (LPTSTR) &szReaders, /* Diabolic cast for buffer auto-allocation */ &dwReadersSz); /* Beg for auto-allocation */ if (rc == SCARD_E_NO_READERS_AVAILABLE) { /* No reader at all */ dwReaders = 0; } else if (rc != SCARD_S_SUCCESS) { printf("SCardListReaders error %08lX\n",rc); break; } else { /* Track events on found readers. */ LPTSTR pReader = szReaders; for (dwReaders=0; dwReaders<MAXIMUM_SMARTCARD_READERS; dwReaders++) { /* End of multi-string array */ if (*pReader == '\0') break; /* Remember this reader's name */ rgscState[dwReaders].szReader = pReader; /* Jump to next entry in multi-string array */ pReader += strlen(pReader) + 1; } } if (first_run) { /* Program startup, display the number of readers */ if (dwReaders == 0) { printf("No PC/SC reader\n\n"); } else { printf("%lu PC/SC reader%s found\n\n", dwReaders, dwReaders ? "s" : ""); } } if (dwReadersOld != dwReaders) { /* Reader added, or reader removed */ /* (re)set the initial state for all readers */ for (i=0; i<dwReaders; i++) rgscState[i].dwCurrentState = SCARD_STATE_UNAWARE; if (!first_run) { int c; /* Not the program startup, explain the event */ if (dwReadersOld > dwReaders) { c = (int) dwReadersOld-dwReaders; printf("%d reader%s ha%s been removed from the system\n\n", c, (c==1)?" ":"s", (c==1)?"s":"ve"); } else { c = (int) dwReaders-dwReadersOld; printf("%d reader%s ha%s been added to the system\n\n", c, (c==1)?" ":"s", (c==1)?"s":"ve"); } } dwReadersOld = dwReaders; } if (dwReaders == 0) { /* We must wait here, because the SCardGetStatusChange doesn't wait */ /* at all in case there's no reader in the system. Silly, isn't it ? */ #ifdef WIN32 Sleep(1000); #endif #ifdef __linux__ sleep(1); #endif } /* * Interesting part of the job : call SCardGetStatusChange to monitor all changes * taking place in the PC/SC reader(s) */ rc = SCardGetStatusChange(hContext, INFINITE, rgscState, dwReaders); if (rc != SCARD_S_SUCCESS) { printf("SCardGetStatusChange error %08lX\n",rc); break; } for (i=0; i<dwReaders; i++) { BOOL just_inserted = FALSE; if (rgscState[i].dwEventState & SCARD_STATE_CHANGED) { /* Something changed since last loop */ if ( (rgscState[i].dwEventState & SCARD_STATE_PRESENT) && !(rgscState[i].dwCurrentState & SCARD_STATE_PRESENT) ) just_inserted = TRUE; /* Remember new current state for next loop */ rgscState[i].dwCurrentState = rgscState[i].dwEventState; } else { /* Nothing new, don't display anything for this reader */ /* (unless we're in the first run) */ if (!first_run) continue; } /* * Display current reader's state * ------------------------------ */ /* Reader's name */ printf("Reader %lu: %s\n", i, rgscState[i].szReader); /* Complete status */ printf("\tCard state:\n"); if (rgscState[i].dwEventState & SCARD_STATE_IGNORE) printf("\t\tIgnore this reader\n"); if (rgscState[i].dwEventState & SCARD_STATE_UNKNOWN) printf("\t\tReader unknown\n"); if (rgscState[i].dwEventState & SCARD_STATE_UNAVAILABLE) printf("\t\tStatus unavailable\n"); if (rgscState[i].dwEventState & SCARD_STATE_EMPTY) printf("\t\tNo card in the reader\n"); if (rgscState[i].dwEventState & SCARD_STATE_PRESENT) printf("\t\tCard present\n"); if (rgscState[i].dwEventState & SCARD_STATE_ATRMATCH) printf("\t\tATR match\n"); if (rgscState[i].dwEventState & SCARD_STATE_EXCLUSIVE) printf("\t\tReader reserved for exclusive use\n"); if (rgscState[i].dwEventState & SCARD_STATE_INUSE) printf("\t\tReader/card in use\n"); if (rgscState[i].dwEventState & SCARD_STATE_MUTE) printf("\t\tCard mute\n"); if (just_inserted) { /* * Display card's ATR * ------------------ */ if (rgscState[i].cbAtr) { printf("\tCard ATR:"); for (j=0; j<rgscState[i].cbAtr; j++) printf(" %02X", rgscState[i].rgbAtr[j]); printf("\n"); } /* * Do the Desfire library test on this card * ---------------------------------------- */ TestDesfire(hContext, rgscState[i].szReader); } } /* Free the list of readers */ if (szReaders != NULL) { SCardFreeMemory(hContext, szReaders); szReaders = NULL; } /* Not the first run anymore */ first_run = FALSE; } rc = SCardReleaseContext(hContext); /* Never go here (Ctrl+C kill us before !) */ return EXIT_FAILURE; }
/* * Class: com_ibm_opencard_terminal_pcsc10_OCFPCSC1 * Method: SCardGetStatusChange * Signature: (II[Lcom/ibm/opencard/terminal/pcsc10/PcscReaderState;)V */ JNIEXPORT void JNICALL Java_com_ibm_opencard_terminal_pcsc10_OCFPCSC1_SCardGetStatusChange (JNIEnv *env, jobject obj, jint context, jint timeout, jobjectArray jReaderState) { SCARD_READERSTATE *readerState; int numReaderState; int ii; long returnCode; jobject objReaderState; jbyteArray jATR; /* First access the PcscReaderState structure to initialize the return */ /* value. Allocate a reader state array for each java ReaderState structure. */ numReaderState = env->GetArrayLength(jReaderState); if (numReaderState < 1) { throwPcscException(env, obj, "SCardGetStatusChange", "size of ReaderState array must be greater than 0 elements", 0); return; } readerState = (SCARD_READERSTATE *)malloc(numReaderState * sizeof(SCARD_READERSTATE)); if (readerState == NULL) { throwPcscException(env, obj, "SCardGetStatusChange", "error allocating memory for the readerState buffer", 0); return; } /* clear the allocated memory */ memset(readerState, 0x00, numReaderState * sizeof(SCARD_READERSTATE)); /* Now get each Java reader state structure and translate it into C++ */ for (ii=0; ii<numReaderState; ii++) { objReaderState = env->GetObjectArrayElement(jReaderState, ii); if (env->ExceptionOccurred() != NULL) { free(readerState); throwPcscException(env, obj, "SCardGetStatusChange", "error getting elements from the readerState array", 0); return; } returnCode = getIntField(env, objReaderState, "CurrentState", (long *)&readerState[ii].dwCurrentState); if (returnCode) { free(readerState); throwPcscException(env, obj, "SCardGetStatusChange", "error getting CurrentState field from the readerState record", 0); return; } returnCode = getIntField(env, objReaderState, "EventState", (long*)&readerState[ii].dwEventState); if (returnCode) { free(readerState); throwPcscException(env, obj, "SCardGetStatusChange", "error getting EventState field from the readerState record", 0); return; } readerState[ii].szReader = (const char *)accessStringField(env, objReaderState, "Reader"); if (readerState[ii].szReader == NULL) { free(readerState); throwPcscException(env, obj, "SCardGetStatusChange", "error getting Reader field from readerState record", 0); return; } int maxSize; returnCode = accessByteArray(env, objReaderState, "UserData", (unsigned char **)&readerState[ii].pvUserData, &maxSize); if (returnCode) { free(readerState); throwPcscException(env, obj, "SCardGetStatusChange", "error getting UserData field from readerState record", 0); return; } } /* set the response timeout to 1000ms */ returnCode = SCardGetStatusChange((SCARDCONTEXT)context, 1000, readerState, numReaderState); if (returnCode != SCARD_S_SUCCESS) { free(readerState); throwPcscException(env, obj, "SCardGetStatusChange", "error executing SCardGetStatusChange", returnCode); return; } readerState[0].dwCurrentState = readerState[0].dwEventState; /* write back the informations from the readerStatus to the java structures */ for (ii=0; ii<numReaderState; ii++) { objReaderState = env->GetObjectArrayElement(jReaderState, ii); if (env->ExceptionOccurred() != NULL) { free(readerState); throwPcscException(env, obj, "SCardGetStatusChange", "error getting array elements", returnCode); return; } returnCode = setIntField(env, objReaderState, "EventState", readerState[ii].dwEventState); if (returnCode) { free(readerState); throwPcscException(env, obj, "SCardGetStatusChange", "error setting the EventState field", returnCode); return; } returnCode = releaseStringField(env, objReaderState, "Reader", (const char *)readerState[ii].szReader); if (returnCode) { free(readerState); throwPcscException(env, obj, "SCardGetStatusChange", "error setting the Reader field", returnCode); return; } returnCode = releaseByteArray(env, objReaderState, "UserData", (unsigned char *)readerState[ii].pvUserData); if (returnCode) { free(readerState); throwPcscException(env, obj, "SCardGetStatusChange", "error setting the UserData", returnCode); return; } // buffer for length of ATR jsize lenATR = (jsize)readerState[0].cbAtr; // check the length of the ATR in the PCSC ReaderState // if > 0 copy ATR to java ReaderState if (lenATR > 0) { // create new java bytearray with length of current ATR jATR = env->NewByteArray(lenATR); // copy PCSC ATR to jATR env->SetByteArrayRegion(jATR, 0, lenATR, (jbyte *)readerState[ii].rgbAtr); // find the ReaderState-Class jclass clsReaderState = env->GetObjectClass(objReaderState); // get the field ID from ATR-field jfieldID fldATR = env->GetFieldID(clsReaderState, "ATR", "[B"); // set the ATR-field within the ReaderStateObject env->SetObjectField(objReaderState, fldATR, jATR); } } free(readerState); return; }
/* * This is the main work of the emulator, handling the thread that looks for * changes in the readers and the cards. */ static void * passthru_emul_event_thread(void *args) { char *reader_list = NULL; int reader_list_len = 0; SCARD_READERSTATE_A *reader_states = NULL; int reader_count = 0; /* number of active readers */ int max_reader_count = 0; /* size of the reader_state array (including inactive readers) */ LONG rv; int timeout=1000; int i; do { /* variables to hold on to our new values until we are ready to replace * our old values */ char *new_reader_list = NULL; int new_reader_list_len = 0; int new_reader_count = 0; /* other temps */ char * reader_entry; VReader *reader; /* * First check to see if the reader list has changed */ rv = SCardListReaders(global_context, NULL, NULL, &new_reader_list_len); if (rv != SCARD_S_SUCCESS) { goto next; } /* * If the names have changed, we need to update our list and states. * This is where we detect reader insertions and removals. */ if (new_reader_list_len != reader_list_len) { /* update the list */ new_reader_list = (char *)malloc(new_reader_list_len); if (new_reader_list == NULL) { goto next; } rv = SCardListReaders(global_context, NULL, new_reader_list, &new_reader_list_len); if (rv != SCARD_S_SUCCESS) { free(new_reader_list); goto next; } /* clear out our event state */ for (i=0; i < reader_count; i++) { reader_states[i].dwEventState = 0; } /* count the readers and mark the ones that are still with us */ for (reader_entry = new_reader_list; *reader_entry; reader_entry += strlen(reader_entry)+1) { SCARD_READERSTATE_A *this_state; new_reader_count++; /* if the reader is still on the list, mark it present */ this_state = passthru_get_reader_state(reader_states, reader_count, reader_entry); if (this_state) { this_state->dwEventState = SCARD_STATE_PRESENT; } } /* eject any removed readers */ for (i=0; i < reader_count; i++) { if (reader_states[i].dwEventState == SCARD_STATE_PRESENT) { reader_states[i].dwEventState = 0; continue; } reader = vreader_get_reader_by_name(reader_states[i].szReader); vreader_remove_reader(reader); vreader_free(reader); reader_states[i].szReader = NULL; } /* handle the shrinking list */ if (new_reader_count < reader_count) { /* fold all the valid entries at the end of our reader_states * array up into those locations vacated by ejected readers. */ for (i=reader_count-1; i < (new_reader_count -1); i--) { if (reader_states[i].szReader) { SCARD_READERSTATE_A *blank_reader; blank_reader = passthru_get_blank_reader(reader_states, new_reader_count); assert(blank_reader); *blank_reader = reader_states[i]; reader_states[i].szReader = NULL; } } } /* handle the growing list */ if (new_reader_count > max_reader_count) { SCARD_READERSTATE_A *new_reader_states; /* grow the list */ new_reader_states = (SCARD_READERSTATE_A *)realloc(reader_states, sizeof(SCARD_READERSTATE_A)*new_reader_count); if (new_reader_states) { /* successful, update our current state */ reader_states = new_reader_states; max_reader_count = new_reader_count; } else { new_reader_count = max_reader_count; /* couldn't get enough * space to handle * all the new readers * */ } /* mark our new entries as empty */ for (i=reader_count; i > new_reader_count; i++) { reader_states[i].szReader = NULL; } } /* now walk the reader list, updating the state */ for (reader_entry = new_reader_list; *reader_entry; reader_entry += strlen(reader_entry)+1) { SCARD_READERSTATE_A *this_state; this_state = passthru_get_reader_state(reader_states, new_reader_count, reader_entry); if (this_state) { /* replace the old copy of the string with the new copy. * This will allow us to free reader_list at the end */ reader_states->szReader = reader_entry; continue; } /* this is a new reader, add it to the list */ this_state = passthru_get_blank_reader(reader_states, new_reader_count); if (!this_state) { continue; /* this can happen of we couldn't get enough slots in the grow list */ } this_state->szReader = reader_entry; this_state->dwCurrentState = SCARD_STATE_UNAWARE; reader = vreader_new(reader_entry, NULL, NULL); if (reader) { vreader_add_reader(reader); } vreader_free(reader); } /* finally update our current variables */ free(reader_list); reader_list = new_reader_list; reader_list_len = new_reader_list_len; reader_count = new_reader_count; } next: rv = SCardGetStatusChange(global_context, timeout, reader_states, reader_count); if (rv == SCARD_E_TIMEOUT) { continue; /* check for new readers */ } if (rv != SCARD_S_SUCCESS) { static int restarts = 0; VCardStatus status; /* try resetting the pcsc_lite subsystem */ SCardReleaseContext(global_context); global_context = 0; /* should close it */ printf("***** SCard failure %x\n", rv); restarts++; if (restarts >= 3) { printf("***** SCard failed %d times\n", restarts); return; /* exit thread */ } status = passthru_pcsc_lite_init(); assert(status == CARD_DONE); sleep(1); continue; } /* deal with card insertion/removal */ for (i=0; i < reader_count ; i++) { if ((reader_states[i].dwEventState & SCARD_STATE_CHANGED) == 0) { continue; } reader_states[i].dwCurrentState = reader_states[i].dwEventState; reader = vreader_get_reader_by_name(reader_states[i].szReader); if (reader == NULL) { continue; } if (reader_states[i].dwEventState & SCARD_STATE_EMPTY) { if (vreader_card_is_present(reader) == VREADER_OK) { vreader_insert_card(reader, NULL); } } if (reader_states[i].dwEventState & SCARD_STATE_PRESENT) { VCard *card; VCardStatus status = VCARD_FAIL; /* if there already was a card present, eject it before we * insert the new one */ if (vreader_card_is_present(reader) == VREADER_OK) { vreader_insert_card(reader, NULL); } card = vcard_new(NULL, NULL); if (card != NULL) { status = passthru_card_init(reader, card, "", NULL, NULL, NULL, 0); passthru_card_set_atr(card, reader_states[i].rgbAtr, reader_states[i].cbAtr); vcard_set_atr_func(card, passthru_card_get_atr); } if (status == VCARD_DONE) { vreader_insert_card(reader, card); } vcard_free(card); } vreader_free(reader); } } while (1); return NULL; }
BOOL MonitorReaders(SCARDCONTEXT hContext) { DWORD dwReaders, dwReadersOld = 0; SCARD_READERSTATE *rgscState; LPSTR szReaders = NULL; DWORD dwReadersSz; DWORD maxReaders; BOOL bFirstRun = TRUE; DWORD i, j; LONG rc; /* Constant MAXIMUM_SMARTCARD_READERS is only 10 in Windows SDK */ /* This is not enough for most of our tests. 64 sounds good... */ maxReaders = MAXIMUM_SMARTCARD_READERS; if (maxReaders<64) maxReaders = 64; rgscState = calloc(maxReaders, sizeof(SCARD_READERSTATE)); if (rgscState == NULL) { printf("Out of memory\n"); return FALSE; } for (;;) { /* Get the list of available readers */ dwReadersSz = SCARD_AUTOALLOCATE; rc = SCardListReaders(hContext, NULL, /* Any group */ (LPTSTR) &szReaders, /* Diabolic cast for buffer auto-allocation */ &dwReadersSz); /* Beg for auto-allocation */ if (rc == SCARD_E_NO_READERS_AVAILABLE) { /* No reader at all */ dwReaders = 0; } else if (rc != SCARD_S_SUCCESS) { printf("SCardListReaders error 0x%08lX (%lu).\n", rc, rc); break; } else { /* Track events on found readers. */ LPTSTR pReader = szReaders; for (dwReaders=0; dwReaders<maxReaders; dwReaders++) { /* End of multi-string array */ if (*pReader == '\0') break; /* Remember this reader's name */ rgscState[dwReaders].szReader = pReader; /* Jump to next entry in multi-string array */ pReader += strlen(pReader) + 1; } } if (bFirstRun) { /* Program startup, display the number of readers */ if (dwReaders == 0) { printf("No PC/SC reader\n\n"); } else { printf("%ld PC/SC reader%s found\n\n", dwReaders, dwReaders ? "s" : ""); } } if (dwReadersOld != dwReaders) { /* Reader added, or reader removed */ /* (re)set the initial state for all readers */ for (i=0; i<dwReaders; i++) rgscState[i].dwCurrentState = SCARD_STATE_UNAWARE; if (!bFirstRun) { int c; /* Not the program startup, explain the event */ if (dwReadersOld > dwReaders) { c = (int) dwReadersOld-dwReaders; printf("%d reader%s ha%s been removed from the system\n\n", c, (c==1)?" ":"s", (c==1)?"s":"ve"); } else { c = (int) dwReaders-dwReadersOld; printf("%d reader%s ha%s been added to the system\n\n", c, (c==1)?" ":"s", (c==1)?"s":"ve"); } } dwReadersOld = dwReaders; } if (dwReaders == 0) { /* We must wait here, because the SCardGetStatusChange doesn't wait */ /* at all in case there's no reader in the system. Silly, isn't it ? */ Sleep(1000); } /* * Interesting part of the job : call SCardGetStatusChange to monitor all changes * taking place in the PC/SC reader(s) */ rc = SCardGetStatusChange(hContext, INFINITE, rgscState, dwReaders); if (rc != SCARD_S_SUCCESS) { printf("SCardGetStatusChange error 0x%08lX (%lu).\n", rc, rc); if (rc == SCARD_F_INTERNAL_ERROR) { /* Oups ? Restard from scratch after 2500ms */ if (szReaders != NULL) { SCardFreeMemory(hContext, szReaders); szReaders = NULL; } Sleep(2500); continue; } break; } for (i=0; i<dwReaders; i++) { BOOL just_inserted = FALSE; if (rgscState[i].dwEventState & SCARD_STATE_CHANGED) { /* Something changed since last loop */ if ( (rgscState[i].dwEventState & SCARD_STATE_PRESENT) && !(rgscState[i].dwCurrentState & SCARD_STATE_PRESENT) ) just_inserted = TRUE; /* Remember new current state for next loop */ rgscState[i].dwCurrentState = rgscState[i].dwEventState; } else { /* Nothing new, don't display anything for this reader */ /* (unless we're in the first run) */ if (!bFirstRun) continue; } if (just_inserted) { printf("Card inserted in %s\n", rgscState[i].szReader); if (rgscState[i].dwEventState & SCARD_STATE_MUTE) { printf("\tCard is mute\n"); } else { printf("\tATR: "); for (j=0; j<rgscState[i].cbAtr; j++) printf("%02X", rgscState[i].rgbAtr[j]); printf("\n"); if (!ProcessCardAtr(hContext, rgscState[i].rgbAtr, rgscState[i].cbAtr)) return FALSE; printf("\n"); } } } /* Free the list of readers */ if (szReaders != NULL) { SCardFreeMemory(hContext, szReaders); szReaders = NULL; } /* Not the first run anymore */ bFirstRun = FALSE; } /* Never go here (Ctrl+C kill us before !) */ free(rgscState); return TRUE; }
LC_CLIENT_RESULT LC_Client_GetNextCard(LC_CLIENT *cl, LC_CARD **pCard, int timeout) { LONG rv; int i; uint32_t progressId; time_t startt; uint64_t to; int distance; assert(cl); startt=time(0); if (timeout==GWEN_TIMEOUT_NONE || timeout==GWEN_TIMEOUT_FOREVER) to=0; else to=timeout; progressId=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY | GWEN_GUI_PROGRESS_ALLOW_EMBED | GWEN_GUI_PROGRESS_SHOW_PROGRESS | GWEN_GUI_PROGRESS_SHOW_ABORT, I18N("Waiting for card to be inserted"), NULL, to, 0); distance=GWEN_GUI_CHECK_PERIOD; if (distance>timeout) distance=timeout; for (;;) { double d; int err; /* continue checking */ for (i=cl->lastUsedReader+1; i<cl->readerCount; i++) { /* we have a change here */ if (cl->readerStates[i].dwEventState & SCARD_STATE_CHANGED) cl->readerStates[i].dwCurrentState=cl->readerStates[i].dwEventState; else continue; DBG_DEBUG(LC_LOGDOMAIN, "Status changed on reader [%s] (%08x, %08x)", cl->readerStates[i].szReader, (unsigned int)(cl->readerStates[i].dwCurrentState), (unsigned int)(cl->readerStates[i].dwEventState)); if (cl->pnpAvailable && i==cl->readerCount-1) { /* pnp pseudo reader: a reader has been added or removed */ DBG_DEBUG(LC_LOGDOMAIN, "Pseudo reader, updating reader list (%08x, %08x)", (unsigned int)(cl->readerStates[i].dwCurrentState), (unsigned int)(cl->readerStates[i].dwEventState)); LC_Client_UpdateReaderStates(cl); cl->lastUsedReader=-1; break; } else { if ((cl->readerStates[i].dwEventState & SCARD_STATE_PRESENT) && !(cl->readerStates[i].dwEventState & SCARD_STATE_EXCLUSIVE) && !(cl->readerStates[i].dwEventState & SCARD_STATE_INUSE)) { LC_CLIENT_RESULT res; LC_CARD *card=NULL; /* card inserted and not used by another application */ DBG_DEBUG(LC_LOGDOMAIN, "Found usable card in reader [%s]", cl->readerStates[i].szReader); res=LC_Client_ConnectCard(cl, cl->readerStates[i].szReader, &card); if (res==LC_Client_ResultOk) { /* card csuccessfully connected, return */ *pCard=card; cl->lastUsedReader=i; GWEN_Gui_ProgressEnd(progressId); return LC_Client_ResultOk; } else { DBG_ERROR(LC_LOGDOMAIN, "Error connecting to card in reader [%s]", cl->readerStates[i].szReader); } } else { DBG_INFO(LC_LOGDOMAIN, "Either no card in reader or card unavailable in reader [%s]", cl->readerStates[i].szReader); } } } if (i>=cl->readerCount) { /* there was no relevant change in a reader, wait for status change */ cl->lastUsedReader=-1; rv=SCardGetStatusChange(cl->scardContext, distance, cl->readerStates, cl->readerCount); if (rv==SCARD_E_TIMEOUT) { /* timeout, just repeat next loop */ if (timeout==GWEN_TIMEOUT_NONE) { GWEN_Gui_ProgressEnd(progressId); return LC_Client_ResultWait; } } else if (rv!=SCARD_S_SUCCESS) { DBG_ERROR(LC_LOGDOMAIN, "SCardGetStatusChange: %d", (int) rv); GWEN_Gui_ProgressEnd(progressId); return LC_Client_ResultIoError; } } /* check timeout */ d=difftime(time(0), startt); if (timeout!=GWEN_TIMEOUT_FOREVER) { if (timeout==GWEN_TIMEOUT_NONE || d>timeout) { DBG_INFO(GWEN_LOGDOMAIN, "Timeout (%d) while waiting, giving up", timeout); GWEN_Gui_ProgressEnd(progressId); return LC_Client_ResultWait; } } /* check for user abort */ err=GWEN_Gui_ProgressAdvance(progressId, (uint64_t)(d*1000)); if (err==GWEN_ERROR_USER_ABORTED) { DBG_ERROR(GWEN_LOGDOMAIN, "User aborted"); GWEN_Gui_ProgressEnd(progressId); return LC_Client_ResultAborted; } } }
bool silvia_pcsc_card_monitor::wait_for_card(silvia_pcsc_card** card) { assert(card != NULL); // First, find which card readers are available LPTSTR readers; LPTSTR readers_orig; DWORD reader_len; LONG rv = SCardListReaders(pcsc_context, NULL, NULL, &reader_len); if ((rv != SCARD_S_SUCCESS) || (reader_len == 0)) { return false; } readers_orig = readers = (LPTSTR) malloc(reader_len * sizeof(char)); rv = SCardListReaders(pcsc_context, NULL, readers, &reader_len); if (rv != SCARD_S_SUCCESS) { free(readers_orig); return false; } // Add readers to availability structure std::vector<SCARD_READERSTATE> reader_states; while (reader_len > 1) { size_t len = strlen(readers); SCARD_READERSTATE reader_state; reader_state.szReader = readers; reader_state.pvUserData = NULL; reader_state.dwCurrentState = SCARD_STATE_UNAWARE; reader_state.dwEventState = SCARD_STATE_UNAWARE; reader_state.cbAtr = MAX_ATR_SIZE; reader_states.push_back(reader_state); reader_len -= len + 1; readers += len + 1; } rv = SCardGetStatusChange(pcsc_context, INFINITE, &reader_states[0], reader_states.size()); if (rv != SCARD_S_SUCCESS) { free(readers_orig); return false; } while (true) { for (std::vector<SCARD_READERSTATE>::iterator i = reader_states.begin(); i != reader_states.end(); i++) { if (FLAG_SET(i->dwEventState, SCARD_STATE_PRESENT)) { // Attempt to connect to this particular card DWORD active_protocol; SCARDHANDLE card_handle; rv = SCardConnect(pcsc_context, i->szReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &card_handle, &active_protocol); if (rv == SCARD_S_SUCCESS) { *card = new silvia_pcsc_card(card_handle, active_protocol, i->szReader); free(readers_orig); return true; } } i->dwCurrentState = i->dwEventState; } rv = SCardGetStatusChange(pcsc_context, INFINITE, &reader_states[0], reader_states.size()); if (rv != SCARD_S_SUCCESS) { break; } } free(readers_orig); return false; }
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 */
/* * Return reader status change. */ JNIEXPORT jint JNICALL GEN_FUNCNAME(Context_NativeGetStatusChange) (JNIEnv *env, jobject _this, jint timeout, jobjectArray jrstates) { SCARD_READERSTATE *crstates; SCARDCONTEXT ctx; jobject jrdrName; jobject jrstate; jboolean isCopy; jbyteArray jatr; DWORD rv; int crcnt; char *catr; int i; ctx = (SCARDCONTEXT) (*env)->GetLongField(env, _this, CtxField); if (jrstates == NULL) { rv = SCardGetStatusChange(ctx, INFINITE, NULL, 0); return rv; } else { crcnt = (*env)->GetArrayLength(env, jrstates); crstates = (SCARD_READERSTATE *)malloc(crcnt * sizeof(SCARD_READERSTATE)); if (crstates == NULL) { pcscex_throw(env, "GetStatusChange(): invalid number of reader-states", 0); return SCARD_E_INVALID_PARAMETER; } for (i = 0; i < crcnt; i++) { jrstate = (*env)->GetObjectArrayElement(env, jrstates, i); if (jrstate == NULL) { free(crstates); npex_throw(env, "GetStatusChange(): invalid null entry in ReaderState array parameter"); return SCARD_E_INVALID_PARAMETER; } crstates[i].dwCurrentState = (*env)->GetIntField(env, jrstate, CurrentStateField); crstates[i].dwEventState = (*env)->GetIntField(env, jrstate, EventStateField); jrdrName = (*env)->GetObjectField(env, jrstate, ReaderStateField); if (jrdrName == NULL) { free(crstates); npex_throw(env, "GetStatusChange(): invalid null reader name entry in one ReaderState parameter"); return SCARD_E_INVALID_PARAMETER; } crstates[i].szReader = (*env)->GetStringUTFChars(env, jrdrName, &isCopy); // copy ATR and check its size. jatr = (jbyteArray) (*env)->GetObjectField(env, jrstate, AtrStateField); if (jatr != NULL) { catr = (*env)->GetByteArrayElements(env, jatr, &isCopy); crstates[i].cbAtr = (*env)->GetArrayLength(env, jatr); if (crstates[i].cbAtr < 0) { free(crstates); npex_throw(env, "GetStatusChange(): invalid zero-length ATR in ReaderState parameter"); return SCARD_E_INVALID_PARAMETER; } if (crstates[i].cbAtr > JPCSC_ATR_SIZE) { free(crstates); npex_throw(env, "GetStatusChange(): invalid ATR length in ReaderState parameter"); return SCARD_E_INVALID_PARAMETER; } memcpy(&crstates[i].rgbAtr[0], catr, crstates[i].cbAtr); (*env)->ReleaseByteArrayElements(env, jatr, catr, JNI_ABORT); } else { crstates[i].cbAtr = 0; } } rv = SCardGetStatusChange(ctx, timeout, &crstates[0], crcnt); if (rv != SCARD_S_SUCCESS) { free(crstates); return rv; } JPCSC_LOG(("NativeGetStatucChange(): readerstate returned ...\n")); pcsc_readerstatea_log(&crstates[0]); for (i = 0; i < crcnt; i++) { jrstate = (*env)->GetObjectArrayElement(env, jrstates, i); (*env)->SetIntField(env, jrstate, CurrentStateField, crstates[i].dwCurrentState); (*env)->SetIntField(env, jrstate, EventStateField, crstates[i].dwEventState); jrdrName = (*env)->GetObjectField(env, jrstate, ReaderStateField); (*env)->ReleaseStringUTFChars(env, jrdrName, crstates[i].szReader); jatr = (*env)->NewByteArray(env, crstates[i].cbAtr); (*env)->SetByteArrayRegion(env, jatr, 0, crstates[i].cbAtr, crstates[i].rgbAtr); (*env)->SetObjectField(env, jrstate, AtrStateField, jatr); } free(crstates); return rv; } }
static uint32 handle_LocateCardsByATR(IRP* irp, tbool wide) { LONG rv; int i, j, k; SCARDCONTEXT hContext; uint32 atrMaskCount = 0; uint32 readerCount = 0; SCARD_READERSTATE* cur = NULL; SCARD_READERSTATE* rsCur = NULL; SCARD_READERSTATE* readerStates = NULL; SERVER_SCARD_ATRMASK* curAtr = NULL; SERVER_SCARD_ATRMASK* pAtrMasks = NULL; stream_seek(irp->input, 0x2C); stream_read_uint32(irp->input, hContext); stream_read_uint32(irp->input, atrMaskCount); pAtrMasks = xmalloc(atrMaskCount * sizeof(SERVER_SCARD_ATRMASK)); if (!pAtrMasks) return sc_output_return(irp, SCARD_E_NO_MEMORY); for (i = 0; i < atrMaskCount; i++) { stream_read_uint32(irp->input, pAtrMasks[i].cbAtr); stream_read(irp->input, pAtrMasks[i].rgbAtr, 36); stream_read(irp->input, pAtrMasks[i].rgbMask, 36); } stream_read_uint32(irp->input, readerCount); readerStates = xzalloc(readerCount * sizeof(SCARD_READERSTATE)); if (!readerStates) return sc_output_return(irp, SCARD_E_NO_MEMORY); for (i = 0; i < readerCount; i++) { cur = &readerStates[i]; stream_seek(irp->input, 4); /* * TODO: on-wire is little endian; need to either * convert to host endian or fix the headers to * request the order we want */ stream_read_uint32(irp->input, cur->dwCurrentState); stream_read_uint32(irp->input, cur->dwEventState); stream_read_uint32(irp->input, cur->cbAtr); stream_read(irp->input, cur->rgbAtr, 32); stream_seek(irp->input, 4); /* reset high bytes? */ cur->dwCurrentState &= 0x0000FFFF; cur->dwEventState &= 0x0000FFFF; cur->dwEventState = 0; } for (i = 0; i < readerCount; i++) { cur = &readerStates[i]; uint32 dataLength; stream_seek(irp->input, 8); stream_read_uint32(irp->input, dataLength); sc_input_repos(irp, sc_input_string(irp, (char **) &cur->szReader, dataLength, wide)); DEBUG_SCARD(" \"%s\"", cur->szReader ? cur->szReader : "NULL"); DEBUG_SCARD(" user: 0x%08x, state: 0x%08x, event: 0x%08x", (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState, (unsigned) cur->dwEventState); if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0) cur->dwCurrentState |= SCARD_STATE_IGNORE; } rv = SCardGetStatusChange(hContext, 0x00000001, readerStates, readerCount); if (rv != SCARD_S_SUCCESS) { DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); return sc_output_return(irp, rv); } DEBUG_SCARD("Success"); for (i = 0, curAtr = pAtrMasks; i < atrMaskCount; i++, curAtr++) { for (j = 0, rsCur = readerStates; j < readerCount; j++, rsCur++) { tbool equal = 1; for (k = 0; k < cur->cbAtr; k++) { if ((curAtr->rgbAtr[k] & curAtr->rgbMask[k]) != (rsCur->rgbAtr[k] & curAtr->rgbMask[k])) { equal = 0; break; } } if (equal) { rsCur->dwEventState |= 0x00000040; /* SCARD_STATE_ATRMATCH 0x00000040 */ } } } stream_write_uint32(irp->output, readerCount); stream_write_uint32(irp->output, 0x00084dd8); stream_write_uint32(irp->output, readerCount); for (i = 0, rsCur = readerStates; i < readerCount; i++, rsCur++) { stream_write_uint32(irp->output, cur->dwCurrentState); stream_write_uint32(irp->output, cur->dwEventState); stream_write_uint32(irp->output, cur->cbAtr); stream_write(irp->output, cur->rgbAtr, 32); stream_write_zero(irp->output, 4); xfree((void*) cur->szReader); } sc_output_alignment(irp, 8); free(readerStates); return rv; }
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; }
void SCardReader::run() { SCARDCONTEXT context; SCARDHANDLE cardHandle; DWORD activeProtocol; DWORD oldEventState; LONG erv; erv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &context); if (SCARD_S_SUCCESS == erv) { LONG crv; crv = SCardConnect(context, (LPCSTR) m_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &cardHandle, &activeProtocol); do { if (SCARD_S_SUCCESS == crv) { SCARD_IO_REQUEST ioRecvPci; BYTE recvBuffer[32]; BYTE sendBuffer[] = {0xFF, 0xCA, 0x00, 0x00, 0x00}; DWORD recvLength = sizeof(recvBuffer); LONG trv; trv = SCardTransmit(cardHandle, SCARD_PCI_T0, sendBuffer, sizeof(sendBuffer),&ioRecvPci, recvBuffer, &recvLength); if (SCARD_S_SUCCESS == trv) { if (recvLength == 6 && recvBuffer[4] == 0x90 && recvBuffer[5] == 0x00) m_cardid = (int)recvBuffer[0] | (int)recvBuffer[1] << 8 | (int)recvBuffer[2] << 16 | (int)recvBuffer[3] << 24; std::cout << m_cardid << " card inserted." << std::endl; if (m_mode == TallyMode) // m_mode(DriverMode) 初始化为DriverMode { //load authentication key recvLength = sizeof(recvBuffer); BYTE loadKey[] = {0xFF, 0x82, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; trv = SCardTransmit(cardHandle, SCARD_PCI_T0, loadKey, sizeof(loadKey), &ioRecvPci, recvBuffer, &recvLength); if (SCARD_S_SUCCESS == trv && recvLength == 2 && recvBuffer[0] == 0x90 && recvBuffer[1] == 0x00) { //authentication key recvLength = sizeof(recvBuffer); BYTE authentication[] = {0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, 0x08, 0x60, 0x00}; trv = SCardTransmit(cardHandle, SCARD_PCI_T0, authentication, sizeof(authentication), &ioRecvPci, recvBuffer, &recvLength); if (SCARD_S_SUCCESS == trv && recvLength == 2 && recvBuffer[0] == 0x90 && recvBuffer[1] == 0x00) { //read binary recvLength = sizeof(recvBuffer); BYTE read[] = {0xFF, 0xB0, 0x00, 0x08, 0x10}; trv = SCardTransmit(cardHandle, SCARD_PCI_T0, read, sizeof(read), &ioRecvPci, recvBuffer, &recvLength); if (SCARD_S_SUCCESS == trv && recvLength == 18 && recvBuffer[16] == 0x90 && recvBuffer[17] == 0x00) { QByteArray array((const char *)recvBuffer, 16); emit dataReady(QString::number(m_cardid), array); } else std::cerr << m_name << " : " << pcsc_stringify_error(trv) << std::endl; } else std::cerr << m_name << " : " << pcsc_stringify_error(trv) << std::endl; } else std::cerr << m_name << " : " << pcsc_stringify_error(trv) << std::endl; } else emit inserted(QString::number(m_cardid)); } else if (SCARD_E_NO_SMARTCARD == trv) std::cerr << m_name << " : " << pcsc_stringify_error(trv) << std::endl; else { std::cerr << m_name << " : " << pcsc_stringify_error(trv) << std::endl; break; } (void) SCardDisconnect(cardHandle, SCARD_RESET_CARD); } if (SCARD_S_SUCCESS == crv || SCARD_E_NO_SMARTCARD == crv) { SCARD_READERSTATE readerStates; LONG grv; readerStates.szReader = m_name; readerStates.dwCurrentState = SCARD_STATE_UNAWARE; grv = SCardGetStatusChange(context, INFINITE, &readerStates, 1); oldEventState = readerStates.dwEventState; do { if (SCARD_S_SUCCESS == grv) { if (readerStates.dwEventState != oldEventState) { //card inserted if ((SCARD_STATE_CHANGED & readerStates.dwEventState) && (SCARD_STATE_PRESENT & readerStates.dwEventState)) break; //card removed if ((SCARD_STATE_CHANGED & readerStates.dwEventState) && (SCARD_STATE_EMPTY & readerStates.dwEventState)) { removed(QString::number(m_cardid)); std::cout << m_cardid << " card removed." << std::endl; } } else QThread::usleep(500); } else if (SCARD_E_TIMEOUT == grv) QThread::sleep(1); else break; oldEventState = readerStates.dwEventState; readerStates.szReader = m_name; readerStates.dwCurrentState = SCARD_STATE_UNAWARE; grv = SCardGetStatusChange(context, INFINITE, &readerStates, 1); } while (true); //quit if fatal error occurs if (SCARD_S_SUCCESS != grv) break; } else { std::cerr << m_name << " : " << pcsc_stringify_error(crv) << std::endl; break; } crv = SCardConnect(context, (LPCSTR) m_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &cardHandle, &activeProtocol); } while(true); } else std::cerr << m_name << " : " << pcsc_stringify_error(erv) << std::endl; std::cout << m_name << " deamon thread has exit." << std::endl; }
PCSC::PCSC( std::string& a_stInputReaderName, u2& a_u2PortNumber, std::string& a_stURI, u4& a_NameSpaceHivecode, u2& a_TypeHivecode, u4& a_Index ) { Log::begin( "PCSC::PCSC" ); m_bDoTransact = true; std::string stIdentifiedReaderName = ""; LPTSTR pReaderList = NULL; if( a_stInputReaderName.empty( ) ) { a_stInputReaderName = "selfdiscover"; } m_hContextPCSC = 0; m_hCardPCSC = 0; LONG lReturn = SCardEstablishContext( 0, NULL, NULL, &m_hContextPCSC ); if( SCARD_S_SUCCESS != lReturn ) { std::string msg = ""; Log::toString( msg, "SCardEstablishContext <%#02x>", lReturn ); Log::error( "PCSC::PCSC", msg.c_str( ) ); throw RemotingException((lpCharPtr)"PCSC: SCardEstablishContext error",lReturn); } // self-discovery mechanism #ifdef WIN32 if (_stricmp("selfdiscover", a_stInputReaderName.c_str()) == 0) { #else if (strncasecmp("selfdiscover", a_stInputReaderName.c_str(),a_stInputReaderName.length()) == 0) { #endif // In Windows SCARD_AUTOALLOCATE (-1) as a value of readerListChatLength // would signal the SCardListReaders to determine the size of reader string // This is not available in Linux so we call the SCardListReaders twice. First // to get the length and then the reader names. #ifdef WIN32 DWORD readerListCharLength = SCARD_AUTOALLOCATE; lReturn = SCardListReaders( m_hContextPCSC, NULL, (LPTSTR)&pReaderList, &readerListCharLength); #else DWORD readerListCharLength = 0; lReturn = SCardListReaders(m_hContextPCSC,NULL,NULL,&readerListCharLength); if(lReturn != SCARD_S_SUCCESS) throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn); pReaderList = (lpCharPtr)malloc(sizeof(char)*readerListCharLength); lReturn = SCardListReaders(m_hContextPCSC, NULL,pReaderList, &readerListCharLength); #endif if(lReturn != SCARD_S_SUCCESS) { std::string msg = ""; Log::toString( msg, "SCardListReaders <%#02x>", lReturn ); Log::error( "PCSC::PCSC", msg.c_str( ) ); throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn); } else { u4 count = 0; u1 foundReader = FALSE; SCARDHANDLE finalCardHandle = 0; try { lpTCharPtr pReader = pReaderList; while ('\0' != *pReader ) { size_t readerNameLen = strlen((const char*)pReader); SCARD_READERSTATE readerStates[1]; readerStates[0].dwCurrentState = SCARD_STATE_UNAWARE; readerStates[0].szReader = pReader; if ( SCardGetStatusChange( m_hContextPCSC, 0, readerStates, 1) == SCARD_S_SUCCESS) { if ((readerStates[0].dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT) { // we found a card in this reader stIdentifiedReaderName = pReader; DWORD activeProtocol; lReturn = SCardConnect( m_hContextPCSC, (LPTSTR)stIdentifiedReaderName.c_str(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &m_hCardPCSC, &activeProtocol); if (lReturn == SCARD_S_SUCCESS) { // try to identify if we're dealing with a .NetCard u1 answerData[258]; DWORD answerLen = 258; Log::log( "PCSC::PCSC SCardTransmit..." ); lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, isNetCardAPDU, sizeof(isNetCardAPDU), NULL, (LPBYTE)answerData, &answerLen); Log::log( "PCSC::PCSC - SCardTransmit <%#02x>", lReturn ); if (lReturn == SCARD_S_SUCCESS) { u1 rethrowException = FALSE; try { if (answerData[answerLen - 2] == 0x61) { if (answerData[answerLen - 1] > 10) { u1Array invokeAPDU(0); invokeAPDU += (u1)0xD8; invokeAPDU += (u2)CARDMANAGER_SERVICE_PORT; invokeAPDU += (u1)0x6F; invokeAPDU += (u4)HIVECODE_NAMESPACE_SMARTCARD; invokeAPDU += (u2)HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER; invokeAPDU += (u2)HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT; std::string* cmServicem_stURI = new std::string(CARDMANAGER_SERVICE_NAME); invokeAPDU.Append(cmServicem_stURI); delete cmServicem_stURI; invokeAPDU += (u4)a_NameSpaceHivecode; invokeAPDU += (u2)a_TypeHivecode; invokeAPDU.Append(&a_stURI); // construct call if(invokeAPDU.GetLength() <= (s4)APDU_TO_CARD_MAX_SIZE) { u1Array apdu(5); apdu.GetBuffer()[0] = 0x80; apdu.GetBuffer()[1] = 0xC2; apdu.GetBuffer()[2] = 0x00; apdu.GetBuffer()[3] = 0x00; apdu.GetBuffer()[4] = (u1)invokeAPDU.GetLength(); apdu += invokeAPDU; u1Array answer(0); Log::log( "PCSC::PCSC - ExchangeData..." ); exchangeData(apdu, answer); Log::log( "PCSC::PCSC - ExchangeData ok" ); Log::log( "PCSC::PCSC - CheckForException..." ); u4 protocolOffset = m_MarshallerUtil.CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32); Log::log( "PCSC::PCSC - CheckForException ok" ); u4 discoveredPortNumber = m_MarshallerUtil.ComReadU4At(answer, protocolOffset); if ((a_u2PortNumber == 0) || (discoveredPortNumber == a_u2PortNumber)) { a_u2PortNumber = (u2)discoveredPortNumber; if (foundReader == TRUE) { if (a_Index == 0) { // this is the second reader/card/app that matches - we error at this point rethrowException = TRUE; std::string errorMessage( "At least 2 cards posses \""); errorMessage += a_stURI.c_str( ); errorMessage += "\" service\r\nRemove conflicting cards from your system"; Log::error( "PCSC::PCSC", errorMessage.c_str( ) ); throw RemotingException(errorMessage); } } foundReader = TRUE; finalCardHandle = m_hCardPCSC; // Advance to the next value. count++; if (count == a_Index) { // we enumerate one by one the valid readers - so stop here break; } pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1); continue; } } } } } catch (...) { if (rethrowException == TRUE) { throw; } else { // swallow exception } } SCardDisconnect( m_hCardPCSC, SCARD_LEAVE_CARD); m_hCardPCSC = 0; } // this is not a .NetCard, or the service was not found - let's try another reader/card else { Log::error( "PCSC::PCSC", "SCardTransmit failed" ); } } else { Log::error( "PCSC::PCSC", "SCardConnect failed" ); } } else { Log::error( "PCSC::PCSC", "SCARD_STATE_PRESENT not present" ); } } else { Log::error( "PCSC::PCSC", "SCardGetStatusChange != SCARD_S_SUCCESS" ); } // Advance to the next value. pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1); } } catch (...) { stIdentifiedReaderName = ""; #ifdef WIN32 /*lReturn = */SCardFreeMemory( m_hContextPCSC, pReaderList); /*if(lReturn != SCARD_S_SUCCESS) { throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn); }*/ #else if( pReaderList ) { free(pReaderList); } #endif throw; } // have we found anything ? if( !foundReader) { stIdentifiedReaderName = ""; #ifdef WIN32 /*lReturn = */SCardFreeMemory( m_hContextPCSC, pReaderList); //if(lReturn != SCARD_S_SUCCESS) { // throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn); //} #else if(pReaderList ) { free(pReaderList); } #endif throw RemotingException((lpCharPtr)"Could not find any .NET smart card", SCARD_E_NO_SMARTCARD ); } m_hCardPCSC = finalCardHandle; } m_stReaderName = stIdentifiedReaderName; } else { m_stReaderName = a_stInputReaderName; } Log::end( "PCSC::PCSC" ); } /* */ void PCSC::exchangeData( u1Array &dataIn, u1Array &dataout ) { // check validity of handle if ( SCARD_S_SUCCESS != SCardIsValidContext( m_hContextPCSC ) ) { throw RemotingException( (lpCharPtr)"PCSC: Invalid handle", SCARD_E_INVALID_HANDLE ); } try { if( m_bDoTransact ) { beginTransaction( ); } unsigned char ucRetry = 0; do { ucRetry++; unsigned char answerData[ 258 ]; memset( answerData, 0, sizeof( answerData ) ); DWORD answerLen = sizeof( answerData ); #ifdef __DEBUG_APDU__ Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Command", dataIn.GetBuffer( ), dataIn.GetLength( ) ); Timer t; t.start( ); #endif LONG lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, dataIn.GetBuffer( ), dataIn.GetLength( ), NULL, (lpByte)answerData, &answerLen ); if( SCARD_S_SUCCESS != lReturn ) { std::string msg = ""; Log::toString( msg, "SCardTransmit <%#02x>", lReturn ); Log::error( "PCSC::ExchangeData", msg.c_str( ) ); } if( ( SCARD_W_REMOVED_CARD == lReturn ) || ( SCARD_W_RESET_CARD == lReturn ) ) { DWORD dwActiveProtocol = SCARD_PROTOCOL_T0; lReturn = SCardReconnect( m_hCardPCSC, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol ); if( SCARD_S_SUCCESS != lReturn ) { std::string msg = ""; Log::toString( msg, "SCardReconnect <%#02x>", lReturn ); Log::error( "PCSC::ExchangeData", msg.c_str( ) ); throw RemotingException( (lpCharPtr)"PCSC: SCardReconnect error", lReturn ); } lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, dataIn.GetBuffer( ), dataIn.GetLength( ), NULL, (lpByte)answerData, &answerLen ); if( SCARD_S_SUCCESS != lReturn ) { Log::log( "PCSC::ExchangeData - SCardTransmit <%#02x>", lReturn ); } } else if( SCARD_S_SUCCESS != lReturn ) { std::string s; Log::toString( s, "SCardTransmit failed <%#02x>", lReturn ); Log::error( "PCSC::ExchangeData", s.c_str( ) ); throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error", lReturn ); } if (answerLen < 2) { Log::error( "PCSC::ExchangeData", "Incorrect length returned" ); throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned",SCARD_F_COMM_ERROR); } if (answerLen > 2) { u1Array temp(answerLen - 2); temp.SetBuffer(answerData); dataout += temp; } u1 sw1 = answerData[answerLen - 2]; u1 sw2 = answerData[answerLen - 1]; #ifdef __DEBUG_APDU__ Log::log( "PCSC::ExchangeData - Status (1) <%02x%02x>", sw1, sw2 ); Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Response", answerData, answerLen ); t.stop( "PCSC::ExchangeData - Response" ); #endif while( (sw1 == 0x61 ) || ( sw1 == 0x9F ) ) { memset( answerData, 0, sizeof( answerData ) ); unsigned char GetResponse[ 5 ]; memset( GetResponse, 0, sizeof( GetResponse ) ); if (sw1 == 0x9F) { GetResponse[0] = 0xA0; } else { GetResponse[0] = 0x00; } GetResponse[1] = 0xC0; GetResponse[2] = 0x00; GetResponse[3] = 0x00; GetResponse[4] = sw2; answerLen = 258; #ifdef __DEBUG_APDU__ Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Command", GetResponse, sizeof( GetResponse ) ); t.start( ); #endif lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen ); if( ( SCARD_W_REMOVED_CARD == lReturn ) || ( SCARD_W_RESET_CARD == lReturn ) ) { DWORD dwActiveProtocol = SCARD_PROTOCOL_T0; lReturn = SCardReconnect( m_hCardPCSC, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol ); lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen ); } else if( SCARD_S_SUCCESS != lReturn ) { std::string s; Log::toString( s, "SCardTransmit failed <%02x>", lReturn ); Log::error( "PCSC::ExchangeData", s.c_str( ) ); throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error", lReturn ); } if( answerLen < 2 ) { Log::error( "PCSC::ExchangeData", "Incorrect length returned" ); throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned", SCARD_F_COMM_ERROR ); } if( answerLen > 2 ) { u1Array temp( answerLen - 2 ); temp.SetBuffer( answerData ); dataout += temp; } sw1 = answerData[ answerLen - 2 ]; sw2 = answerData[ answerLen - 1 ]; #ifdef __DEBUG_APDU__ Log::log( "PCSC::ExchangeData - Status (2) <%02x%02x>", sw1, sw2 ); Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Response", answerData, answerLen ); t.stop( "PCSC::ExchangeData - Response" ); #endif } // The response is not acceptable. We have to retry the data transmission if( ( 0x63 == sw1 ) || ( ( 0x69 == sw1 ) && ( 0x99 == sw2 ) ) ) { Log::log( "PCSC::ExchangeData - Invalid response. Retry" ); } else { break; } /* if( ( 0x90 == sw1 ) && ( 0x00 == sw2 ) ) { break; }*/ } while ( 3 > ucRetry ); } catch (...) { if( m_bDoTransact ) { endTransaction( ); } throw; } if( m_bDoTransact ) { endTransaction( ); } } /* Cleanup the context and card handle */ PCSC::~PCSC( ) { if( m_hCardPCSC ) { SCardDisconnect( m_hCardPCSC, SCARD_LEAVE_CARD ); m_hCardPCSC = 0; } if( m_hContextPCSC ) { SCardReleaseContext( m_hContextPCSC ); m_hContextPCSC = 0; } } MARSHALLER_NS_END
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); } }
static int pcsc_connect(cardreader_t *cr, unsigned prefered_protocol) { DWORD attr_maxinput = 0; DWORD attr_maxinput_len = sizeof(unsigned int); SCARD_READERSTATE reader_state; pcsc_data_t* pcsc = cr->extra_data; int counter = 0; void *progress; memset(&reader_state,0,sizeof(reader_state)); reader_state.szReader = cr->name+7; reader_state.dwCurrentState = SCARD_STATE_UNAWARE; pcsc->status = SCardGetStatusChange(pcsc->hcontext,INFINITE,&reader_state,1); if (pcsc->status != SCARD_S_SUCCESS) { log_printf(LOG_ERROR,"Failed to query reader status before connecting: %s (error 0x%08x).", pcsc_stringify_error(pcsc->status), pcsc->status ); return 0; } progress = ui_inprogress_new("Connection","Waiting for the reader to connect to a card."); while ((reader_state.dwEventState & SCARD_STATE_PRESENT)==0) { reader_state.dwCurrentState = reader_state.dwEventState; if (((counter++)%30)==0) { log_printf(LOG_INFO,"Waiting for card to be present (current state: %s)...", pcsc_stringify_state(reader_state.dwEventState)); } if (!ui_inprogress_pulse(progress)) { log_printf(LOG_ERROR,"Connection aborted by user"); ui_inprogress_free(progress); pcsc->status = 0x6FFF; return 0; } pcsc->status = SCardGetStatusChange(pcsc->hcontext,100,&reader_state,1); if ((pcsc->status!=(LONG)SCARD_S_SUCCESS) && (pcsc->status!=(LONG)SCARD_E_TIMEOUT)) { log_printf(LOG_ERROR,"Failed to query reader status change before connecting: %s (error 0x%08x/%08x).", pcsc_stringify_error(pcsc->status), pcsc->status, SCARD_E_TIMEOUT ); return 0; } } ui_inprogress_free(progress); log_printf(LOG_DEBUG,"Attempting to connect to '%s'",cr->name); pcsc->status = SCardConnect(pcsc->hcontext, cr->name+7, /* SCARD_SHARE_EXCLUSIVE, */ SCARD_SHARE_SHARED, prefered_protocol, &(pcsc->hcard), &(cr->protocol)); if (pcsc->status!=SCARD_S_SUCCESS) { log_printf(LOG_ERROR,"Connection failed: %s (error 0x%08x).", pcsc_stringify_error(pcsc->status), pcsc->status ); return 0; } if (SCardGetAttrib(pcsc->hcard,SCARD_ATTR_MAXINPUT,(LPBYTE)&attr_maxinput,(LPDWORD)&attr_maxinput_len)==SCARD_S_SUCCESS) log_printf(LOG_INFO,"Reader maximum input length is %u bytes",attr_maxinput); else log_printf(LOG_DEBUG,"Could not determinate reader maximum input length"); log_printf(LOG_INFO,"Connection successful, protocol is %s",pcsc_stringify_protocol(cr->protocol)); cr->connected=1; return 1; }
static uint32 handle_GetStatusChange(IRP* irp, tbool wide) { LONG rv; SCARDCONTEXT hContext; DWORD dwTimeout = 0; DWORD readerCount = 0; SCARD_READERSTATE *readerStates, *cur; int i; stream_seek(irp->input, 0x18); stream_read_uint32(irp->input, dwTimeout); stream_read_uint32(irp->input, readerCount); stream_seek(irp->input, 8); stream_read_uint32(irp->input, hContext); stream_seek(irp->input, 4); DEBUG_SCARD("context: 0x%08x, timeout: 0x%08x, count: %d", (unsigned) hContext, (unsigned) dwTimeout, (int) readerCount); if (readerCount > 0) { readerStates = xzalloc(readerCount * sizeof(SCARD_READERSTATE)); if (!readerStates) return sc_output_return(irp, SCARD_E_NO_MEMORY); for (i = 0; i < readerCount; i++) { cur = &readerStates[i]; stream_seek(irp->input, 4); /* * TODO: on-wire is little endian; need to either * convert to host endian or fix the headers to * request the order we want */ stream_read_uint32(irp->input, cur->dwCurrentState); stream_read_uint32(irp->input, cur->dwEventState); stream_read_uint32(irp->input, cur->cbAtr); stream_read(irp->input, cur->rgbAtr, 32); stream_seek(irp->input, 4); /* reset high bytes? */ cur->dwCurrentState &= 0x0000FFFF; cur->dwEventState &= 0x0000FFFF; cur->dwEventState = 0; } for (i = 0; i < readerCount; i++) { cur = &readerStates[i]; uint32 dataLength; stream_seek(irp->input, 8); stream_read_uint32(irp->input, dataLength); sc_input_repos(irp, sc_input_string(irp, (char **) &cur->szReader, dataLength, wide)); DEBUG_SCARD(" \"%s\"", cur->szReader ? cur->szReader : "NULL"); DEBUG_SCARD(" user: 0x%08x, state: 0x%08x, event: 0x%08x", (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState, (unsigned) cur->dwEventState); if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0) cur->dwCurrentState |= SCARD_STATE_IGNORE; } } else { readerStates = NULL; } rv = SCardGetStatusChange(hContext, (DWORD) dwTimeout, readerStates, (DWORD) readerCount); if (rv != SCARD_S_SUCCESS) DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv); else DEBUG_SCARD("Success"); stream_write_uint32(irp->output, readerCount); stream_write_uint32(irp->output, 0x00084dd8); stream_write_uint32(irp->output, readerCount); for (i = 0; i < readerCount; i++) { cur = &readerStates[i]; DEBUG_SCARD(" \"%s\"", cur->szReader ? cur->szReader : "NULL"); DEBUG_SCARD(" user: 0x%08x, state: 0x%08x, event: 0x%08x\n", (unsigned) cur->pvUserData, (unsigned) cur->dwCurrentState, (unsigned) cur->dwEventState); /* TODO: do byte conversions if necessary */ stream_write_uint32(irp->output, cur->dwCurrentState); stream_write_uint32(irp->output, cur->dwEventState); stream_write_uint32(irp->output, cur->cbAtr); stream_write(irp->output, cur->rgbAtr, 32); stream_write_zero(irp->output, 4); xfree((void *)cur->szReader); } sc_output_alignment(irp, 8); xfree(readerStates); return rv; }
void PCSCResourceManager::run() { SCARDCONTEXT context; LONG rv; while (true) { rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &context); if (rv == SCARD_S_SUCCESS) { DWORD readerNum = SCARD_AUTOALLOCATE; LPSTR readerNames = NULL; do { rv = SCardListReaders(context, NULL, (LPSTR) &readerNames, &readerNum); if (rv == SCARD_S_SUCCESS) { for (LPCSTR pch = readerNames; *pch != '\0'; pch += strlen(pch) + 1) { int i; for (i = 0; i < m_availabeReaders.size(); i++) if (0 == strcmp(m_availabeReaders[i]->name(), pch)) break; if (i == m_availabeReaders.size()) { SCardReader *reader = new SCardReader(pch); m_availabeReaders.append(reader); connect(reader, SIGNAL(unavailable(LPCSTR)), SLOT(clearUnavailabeReader(LPCSTR))); reader->start(); emit readerPluged(reader); } } (void) SCardFreeMemory(context, readerNames); } else std::cout << pcsc_stringify_error(rv) << std::endl; if (rv == SCARD_S_SUCCESS || rv == SCARD_E_NO_READERS_AVAILABLE) { SCARD_READERSTATE readerStates; readerStates.szReader = "\\\\?PnP?\\Notification"; readerStates.dwCurrentState = SCARD_STATE_UNAWARE; rv = SCardGetStatusChange(context, INFINITE, &readerStates, 1); if (rv != SCARD_E_TIMEOUT || rv != SCARD_S_SUCCESS) { (void) SCardReleaseContext(context); break; } } else { (void) SCardReleaseContext(context); break; } } while (true); } else { std::cout << pcsc_stringify_error(rv) << std::endl; QThread::sleep(PCSC_ERROR_BREAK_TIME); } } }