Search code examples
c#nfcsmartcard-readerpcscwinscard

ACR1252 NFC Reader Serial Number


I bought a couple of ACR1252 NFC readers, as they seem to be the only ones that can store and return an internal serial number. I need them for a C# program, where I need to distinguish 2 NFC readers plugged to the same computer, since Windows assigns the names in order of connection and could be changed.

My problem is: How can I access the command that returns the serial number without having an NFC card over the reader? It only works when the reader is reading a card.

My code (abbreviated) is something like this:

public void getReaderSerialNumer()
{
    int retCode = Card.SCardEstablishContext(Card.SCARD_SCOPE_SYSTEM, 0, 0, ref hContext);
    readername = "ACS ACR1252 1S CL Reader PICC 0";
    retCode = Card.SCardConnect(hContext, readername, Card.SCARD_SHARE_DIRECT, Card.SCARD_PROTOCOL_T0 | Card.SCARD_PROTOCOL_T1, ref hCard, ref Protocol);

    byte[] sendBytes = new byte[] { 0xE0, 0x00, 0x00, 0x33, 0x00 };
    int pcBytesReturned = 0;
    Byte[] RecieveBuff = new Byte[64];
    uint controlcode = 3225264;

    retCode = Card.SCardControl(hCard, controlcode, ref sendBytes[0], sendBytes.Length, ref RecieveBuff[0], RecieveBuff.Length, ref pcBytesReturned);

    char[] outchar = System.Text.Encoding.UTF8.GetString(RecieveBuff).ToCharArray();
    uint pCard = (uint)hCard;
    retCode = Card.SCardDisconnect((int)pCard, Card.SCARD_RESET_CARD);
}

Just the first command SCardEstablishContext works without a card. But for SCardConnect and SCardControl I get error if there is no card on the reader.

SCardConnect returns retCode = -2146434967

SCardControl returns retCode = 6

But I need the 3 commands in order to get:

SCardEstablishContext -> hContext -> SCardConnect -> hCard -> SCardControl -> Serial Number of the reader

How can I get the reader serial number with no card attached to it (just the reader plugged to USB port)?


Solution

  • In order to get calls to SCardConnect() succeed without a card present on the reader, you will need to use the parameter SCARD_SHARE_DIRECT in combination with setting the preferred protocols argument to 0:

    retCode = Card.SCardConnect(hContext, readername, Card.SCARD_SHARE_DIRECT, 0, ref hCard, ref Protocol);
    

    See SCardConnect function, dwPreferredProtocols:

    This parameter may be zero only if dwShareMode is set to SCARD_SHARE_DIRECT. In this case, no protocol negotiation will be performed by the drivers until an IOCTL_SMARTCARD_SET_PROTOCOL control directive is sent with SCardControl.

    However, be aware that you will usually need to install the driver from the ACS website since other drivers might not provide the capabilities for this type of escape commands.