2

Well these days Im trying to design a software which use smart card readers, I am using ACR1252u and I have discovered how to buzz my smart card reader if a tag or card is on the reader. but still wondering how can I do this without the card on the reader. the code which works for when the card is on the reader is below:

retCode = Card.SCardConnect(hContext, readername, Card.SCARD_SHARE_SHARED,
Card.SCARD_PROTOCOL_T0 | Card.SCARD_PROTOCOL_T1, ref hCard, ref Protocol);

    Byte[] setBuzzerLoud = new Byte[6];
    setBuzzerLoud[0] = 0xE0;
    setBuzzerLoud[1] = 0x00;
    setBuzzerLoud[2] = 0x00;
    setBuzzerLoud[3] = 0x21;
    setBuzzerLoud[4] = 0x01;
    setBuzzerLoud[5] = 0x77;
    uint pcBytesReturned = 0;
    Byte[] RecieveBuff = new Byte[64];
    uint controlcode = 3225264;
    int status = Card.SCardControl(hCard, controlcode, ref setBuzzerLoud[0], 6, ref RecieveBuff[0], RecieveBuff.Length, ref pcBytesReturned);
MessageBox.Show(status.ToString());

The problem is when hcard is on the reader the status which is the error shows 6. which means wrong handle!. But why buzzing a reader is connected to if the card is over the reader? is there anyway to turn this over? cause after this I want to turn on LEDs while the card is not over the reader- Guys plz if anyone have solved this problem tell us.

  • This really is wrong forum, i imagine that there are better places to ask these questions, perhaps call ACS, the maker of the reader and designer of the API? – jogco Jul 19 '16 at 21:09
  • But I think they do this with PS SC communications which is written in windows.h, the point is which function can set the reader without using hcard handle! – Farzad Moghaddampoor Jul 19 '16 at 21:24
  • Ok, i did this, googled your readers name, got the ACS site from the result, found a pdf describing the API, read some.. ..and found this lube: "The reader's peripheral control commands are implemented by using SCardControl with Control Code SCARD_CTL_CODE(3500)". And by the look of it, you are using the PCSC API. – jogco Jul 20 '16 at 05:49
  • I knew that , I also found uint controlcode = 3225264; by debugging SCARD_CTL_CODE(3500) in c++. the problem is with windows.h functions which are scardcontrol and scardTransmit. and they give errors when the card is not on the card reader. and I want to control the reader without presence of the card!. my objective is to turn off the Rf ,Leds and buzzer when the card is on it; and then if i trigger a button in my software while the card is not present on the reader all of these turn on. – Farzad Moghaddampoor Jul 20 '16 at 07:29
  • The cause is that SCARD_CTL_CODE is a macro that is resolved at compile, there is no guarantee that you get that particular uint. So you do right by calling the macro as in you answer. – jogco Jul 20 '16 at 08:59
  • Great, thanks for the help. Still wondering how i can convert this line into c# DWORD controlcode = SCARD_CTL_CODE(3500); – Farzad Moghaddampoor Jul 20 '16 at 09:27

2 Answers2

2

I have found the solution in a c++ code: only in the linker we need to add winscard.h

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <cstdint>
#include <cstring>
#include <winscard.h>

std::wstring s2ws(const std::string& s);

int main(int argc, char* argv[]) {
    SCARDCONTEXT context = 0;
    LONG ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, nullptr, nullptr, &context);

    if (ret != SCARD_S_SUCCESS) {
        std::cout << "SCardEstablishContext: " << ret<< std::endl;
    }
    else {
        LPTSTR allReaderNames = nullptr;
        DWORD readerCount = SCARD_AUTOALLOCATE;

        ret = SCardListReaders(context, nullptr, reinterpret_cast<LPTSTR>(&allReaderNames), &readerCount);

        if (ret != SCARD_S_SUCCESS) {
            std::cout << "SCardListReaders: " << ret << std::endl;
        }
        else {
            std::string readerName("ACS ACR1252 1S CL Reader PICC 0");
            std::wstring stemp = s2ws(readerName);
            LPCWSTR result = stemp.c_str();
            DWORD activeProtocol = 0;
            SCARDHANDLE card = 0;

            ret = SCardConnect(context, result, SCARD_SHARE_DIRECT, 0, &card, &activeProtocol);

            if (ret != SCARD_S_SUCCESS) {
                std::cout << "SCardConnect: " << ret << std::endl;
            }
            else {
                std::vector<std::uint8_t> outputBuffer{ 0xE0, 0x0, 0x0, 0x21, 0x01, 0x71 };
                std::vector<std::uint8_t> inputBuffer(64, 0);
                DWORD bytesReturned = 0;

                DWORD controlcode = SCARD_CTL_CODE(3500);
                ret = SCardControl(card, controlcode, outputBuffer.data(), outputBuffer.size(), inputBuffer.data(), inputBuffer.size(), &bytesReturned);

                if (ret != SCARD_S_SUCCESS) {
                    std::cout << "SCardControl: " << ret << std::endl;
                }
                else {
                    std::cout << "Response: " << std::hex << std::setfill('0');
                    for (std::size_t i = 0; i < bytesReturned; ++i) {
                        std::cout << std::setw(2) << static_cast<std::uint32_t>(inputBuffer[i]) << " ";
                    }
                    std::cout << std::dec << std::endl;

                    SCardDisconnect(card, SCARD_LEAVE_CARD);
                }
            }

            // Release the memory that SCardListReaders allocated for us
            SCardFreeMemory(context, allReaderNames);
        }

        ret = SCardReleaseContext(context);

        if (ret != SCARD_S_SUCCESS) {
            std::cout << "SCardReleaseContext: " << ret << std::endl;
        }
        std::getchar();
    }

    return 0;
}

std::wstring s2ws(const std::string& s)
{
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}
Jacobm001
  • 11,898
  • 7
  • 46
  • 56
0

The problem with your code is that you call Card.SCardConnect() with Card.SCARD_PROTOCOL_T0 | Card.SCARD_PROTOCOL_T1. This is not allowed when there is no card in the reader. Replace that part with 0, then the call will succeed.

AndreKR
  • 111
  • 4