1

エストニアの ID カードの個人ファイルを読み取ろうとしています。

個人ファイルからレコードを読み取るために、次のデータをカードに送信する必要があります ( ここから) (つまり、ID 番号、名前など)。

00 A4 00 0C          # We choose root folder
00 A4 01 0C 02 EE EE # We choose folder EEEE
00 A4 02 04 02 50 44 # We choose file 5044, which contains personal data
00 B2 XX 04          # We read record XX (see table) from the personal data file
                     # The card responds 61 YY, where YY denotes the number of bytes waiting to be read
00 C0 00 00 YY       # We read YY bytes from the card
                     # Card responds ... 90 00, where ... is the requested data and 90 00 means status OK 

ただし、raw バイトは T=0 プロトコルにあり、カードは T=0 を受け入れる前に不当に長い時間 T=1 でスタックします。イベントのシーケンスは次のとおりです。

  1. カードがリーダーに取り付けられている
  2. プログラムから戻り、SCardStatusChangeカードの処理を開始します
  3. SCardConnectカード (または)に接続しようとすると、約 5 秒間、何度もSCardReconnectエラーが表示されます。SCARD_E_SHARING_VIOLATION
  4. 次に、接続しようとすると、エラーSCARD_E_PROTO_MISMATCHが 3 秒から 30 秒の間、​​場合によってはそれ以上受信されます。
  5. その後、カードは正常に接続され、データが読み取られます。

T=0 プロトコルでどうにかしてより速く接続できますか?

ソースコードの簡略版は次のとおりです。

// NOTE: this is approximately what I do.
// I haven't tested this code yet - it's almost 1 AM here.
#include <winscard.h>
void readSmartCard() {
    LONG sCardErrorCode;
    SCARDCONTEXT sCardContext;
    DWORD sCardReaderStrLen = 1024;
    wchar_t sCardReaderStr[1024];
    SCARDHANDLE sCardHandle;
    DWORD sCardActiveProtocol;
    SCARD_READERSTATE readerState;

    sCardErrorCode = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &sCardContext);

    // error handling macro

    ZeroMemory(&sCardReaderState, sizeof(sCardReaderState));
    sCardReaderState.szReader = L"\\\\?PnP?\\Notification";
    sCardReaderState.pvUserData = nullptr;
    sCardReaderState.dwEventState = SCARD_STATE_PRESENT;

    sCardErrorCode = SCardGetStatusChange(sCardContext, INFINITE, &readerState, 1);

    // e.h.m

    if (readerState.dwCurrentState == 65538) {
        sCardErrorCode = SCardListReaders(sCardContext, NULL, sCardReaderStr, &sCardReaderStrLen);
        // e.h.m
        readerState.szReader = sCardReaderStr;
    }

    sCardErrorCode = SCardGetStatusChange(sCardContext, INFINITE, &readerState, 1);
    // e.h.m

    if (sCardReaderState.dwEventState & SCARD_STATE_PRESENT) {

        while (true) {
            sCardErrorCode = SCardConnect(sCardContext, readerState.szReader, SCARD_SHARE_EXCLUSIVE,
                SCARD_PROTOCOL_T0, &sCardHandle, &sCardActiveProtocol);

            // e.h.m
            printf("%x", sCardErrorCode); 
            // this will print:
            // 8010000b (for around 5s)
            // 8010000f (for around 20s)
            if (sCardErrorCode == SCARD_S_SUCCESS) {
                break;
            }
            Sleep(1000);
        }

        // open personal file and read data, yay!
    }
}
4

2 に答える 2

0

プロトコルのみSCardConnect()への排他的アクセスを要求しているため、カードが使用されている場合は返され、カードが使用されていないがアクティブな場合は代わりに返されます。T0SCARD_E_SHARING_VIOLATIONT1SCARD_E_PROTO_MISMATCH

が通知を報告するときSCardGetStatusChange()は、フラグのみをチェックしていSCARD_STATE_PRESENTますが、無視している他のフラグも存在する場合がありますSCARD_STATE_INUSE

リーダーへの排他的アクセスが必要な場合は、SCARD_STATE_INUSEがクリアされるか、SCARD_E_SHARING_VIOLATIONレポートが開始されなくなるまで待つ必要があります。排他モードではなく共有モードでの接続を許可するようにロジックを変更しない限り、それについては何もできません。

現在のプロトコルに関係なくリーダーに接続したい (したがって、より早く排他的アクセスを取得したい) 場合は、パラメーターでそれらを OR することにより、とプロトコルの両方SCardConnect()を同時に受け入れるように要求できます (ドキュメント)。次に、パラメーターがアクティブなプロトコルを出力する場合、カードを読み取る前に、プロトコルへのステータス変更を待つことができます。 T0T1dwPreferredProtocolpdwActiveProtocolT1T0

于 2016-09-28T22:54:06.523 に答える