WinScard SCardConnect returns SCARD_E_NOT_READY

5.7k views Asked by At

I have a program in Java that successfully communicates with a Java Smart Card with a smart card reader using javax.smartcardio.*. With API monitor I have found out that the java.exe witch runs it is actually using WinSCard winAPI (It loads winscard.dll the moment I start communicating. I did not manage to find our the actual calls yet)

My problem is that I tried to implement the same thing in a Qt framework C++ program using the WinSCard library. Everything work well if I run the program in 10 seconds after the reader is plugged in the USB, but after that the reader goes into a state that I presume is some powers saving state, then a few seconds later it shots down the USB pipe. The java program automatically "wakes up" the reader when I try to connect to it, but the C++ I wrote does not, and I don't know what I'm doing wrong.

First I establish a context with SCardEstablishContext() call, then I list readers with SCardListReaders(), which actually list the reader is question, the finally I call SCardConnect() to connect, with returns SCARD_E_NOT_READY if the smart card reader is in this "sleep" state.

Please note that if the smart card reader is not is this "sleep" mode, I can communicate with the card with no problem with the same code.

The winAPI description gives no hint on what to do in this case, and I could not find any trace of what to do. If anyone knows a solution for this, please share!

2

There are 2 answers

2
FPGA warrior On BEST ANSWER

The misery is solved.: Underdocumented windows api OR windows api bug OR bad smart card reader driver implementation.

The SCardConnect() windows api states that:

dwShareMode [in] A flag that indicates whether other applications may form connections to the card.

SCARD_SHARE_SHARED: This application is willing to share the card with other applications. SCARD_SHARE_EXCLUSIVE: This application is not willing to share the card with other applications. SCARD_SHARE_DIRECT: This application is allocating the reader for its private use, and will be controlling it directly. No other applications are allowed access to it.

It seams that in case of SCARD_SHARE_DIRECT it also does not allows access to whatever was meant to wake the sleeping reader. In case of SCARD_SHARE_EXCLUSIVE or SCARD_SHARE_SHARED, its works like a charm: the reader "wakes up" automatically on SCardConnect().

3
Greycon On

I do that, with the following code, it seems to work fine. (Although it's pretty old now.) Here's what I do:

int connectDevice(bool cardNeeded){
    dwAP = 0;

    log("\nEstablishing a connection to the device\n");

    if (deviceConnected) {
        log("Already connected.\n");
        return 1;
    }   

    hCard  = NULL;
    if (cardNeeded) {
        lReturn = SCardConnect(hContext, (LPCTSTR)currentReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_Tx, &hCard, &dwAP );
        if(SCARD_S_SUCCESS != lReturn){
            logBytes("  SCardConnect failed with error: ", (byte *)&lReturn, sizeof(LONG));
            return 0;
        }
    }
    else {
        lReturn = SCardConnect(hContext, (LPCTSTR)currentReader, SCARD_SHARE_DIRECT, 0, &hCard, &dwAP );
        if(SCARD_S_SUCCESS != lReturn){
            logBytes("  SCardConnect failed with error: ", (byte *)&lReturn, sizeof(LONG));
            return 0;
        }
    }
    deviceConnected = true;
    logBytes("  SCardConnect succeeded, handle : ", (byte *)&hCard, sizeof(SCARDHANDLE));
    log("  Successful\n");
    return 1;
}