For Windows Developer

The reader using under Windows using the WINSCARD API, it is standard API by microsoft. you will need add below files into your project:

winscard.h

wintype.h

winscard.dll or winscard.lib

Languages

C to get reader USB iSerialNumber

/*
* Support for Feitian OEM R301E2 Card Reader to get SN from USB description
*
* Copyright (C) Feitian 2016, Ben <ben@ftsafe.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/*
*USB Device Path Format
*
*In most cases, Windows formats the USB device path as follows:
*
*\?usb#vid_vvvv&pid_pppp#ssss#{gggggggg-gggg-gggg-gggg-gggggggggggg}
*
*Where:
*vvvv is the USB vendor ID represented in 4 hexadecimal characters.
*pppp is the USB product ID represented in 4 hexadecimal characters.
*ssss is the USB serial string represented in n characters.
*gggggggg-gggg-gggg-gggg-gggggggggggg is the device interface GUID that is used to link applications to device with specific drivers loaded.
*
*The CP210x VCP driver GUID is:
*
*{A2A39220-39F4-4b88-AECB-3D86A35DC748}
*
*The GUID is assigned in the driver or driver INF file and is used by the application to filter devices that have loaded that driver.
*
*Composite USB Device Path Format For Interfaces
*
*For a composite device with multiple interfaces, the device path for each interface might look something like:
*
*\?usb#vid_vvvv&pid_pppp&mi_ii#aaaaaaaaaaaaaaaa#{gggggggg-gggg-gggg-gggg-gggggggggggg}
*
*Where: 
*vvvv is the USB vendor ID represented in 4 hexadecimal characters.
*pppp is the USB product ID represented in 4 hexadecimal characters.
*ii is the USB interface number.
*aaaaaaaaaaaaaaaa is a unique, Windows-generated string based on things such as the physical USB port address and/or interface number.
*gggggggg-gggg-gggg-gggg-gggggggggggg is the device interface GUID that is used to link applications to device with specific drivers loaded.
*
*/
#include <windows.h>
#include <stdio.h>
#include <Shlwapi.h>
#include <conio.h>
#include <setupapi.h> 

#pragma comment(lib,"setupapi.lib")

static /*const*/ GUID GUID_DEVINTERFACE_USB_DEVICE = 
{ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };

int main()
{
    unsigned int idVendor = 0x00;    //VID
    unsigned int idProduct = 0x00;    //PID
    unsigned char iSerialNumber[256] = {0}; //SN
    BOOL bRet = FALSE;
    HDEVINFO hDevInfo;
    // Get device interface info set handle for all devices attached to system
    hDevInfo = SetupDiGetClassDevs(
        &GUID_DEVINTERFACE_USB_DEVICE, /* CONST GUID * ClassGuid - USB class GUID */
        NULL, /* PCTSTR Enumerator */
        NULL, /* HWND hwndParent */
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE /* DWORD Flags */
        );
    if (hDevInfo == INVALID_HANDLE_VALUE) {
        printf("SetupDiClassDevs failed. GetLastError() returns: 0x%x\n", GetLastError());
        return -1;
    }
    //Retrieve a context structure for a device interface of a device information set.
    DWORD dwIndex = 0;
    SP_DEVICE_INTERFACE_DATA devInterfaceData;
    ZeroMemory(&devInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
    devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    ULONG neededLength, requiredLength;
    PSP_DEVICE_INTERFACE_DETAIL_DATA ClassDeviceData;
    while (TRUE) {
        bRet = SetupDiEnumDeviceInterfaces(
            hDevInfo, /* HDEVINFO DeviceInfoSet */
            NULL, /* PSP_DEVINFO_DATA DeviceInfoData */
            &GUID_DEVINTERFACE_USB_DEVICE, /* CONST GUID * InterfaceClassGuid */
            dwIndex,
            &devInterfaceData /* PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData */
            );

        //If no more items, then break
        if(!bRet && (GetLastError() == ERROR_NO_MORE_ITEMS)){
            break;
        }
        else {
            SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfaceData, NULL, 0, &requiredLength, NULL);
            neededLength = requiredLength;
            ClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(neededLength);
            ClassDeviceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

            //Call SetupDiGetDeviceInterfaceDetail again to get required lenght
            if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfaceData, ClassDeviceData, neededLength, &requiredLength, NULL))
            {
                free(ClassDeviceData);
                SetupDiDestroyDeviceInfoList(hDevInfo);
                return   -1;
            }
            /*
             *\?usb#vid_vvvv&pid_pppp#ssss#{gggggggg-gggg-gggg-gggg-gggggggggggg}
             *vvvv is the USB vendor ID represented in 4 hexadecimal characters.
             *pppp is the USB product ID represented in 4 hexadecimal characters.
             *ssss is the USB serial string represented in n characters.
             *gggggggg-gggg-gggg-gggg-gggggggggggg is the device interface GUID that is used to link applications to device with specific drivers loaded.
             */
            //Get VID, PID, iSerialnumber, GUID
            sscanf(ClassDeviceData->DevicePath, ("\\\\?\\usb#vid_%04X&pid_%04X%#%[^#]"),&idVendor,&idProduct, iSerialNumber);
            if(idVendor == 0x096E && idProduct == 0x0503)
            {
                printf("%s\n", iSerialNumber);
                break;
            }else{
                printf("Detect USB device:\n%s\n", ClassDeviceData->DevicePath);
            }
            free(ClassDeviceData);

        }
        dwIndex++;
    }

    SetupDiDestroyDeviceInfoList(hDevInfo);

    return 0;
}

C for winscard API


#include <stdio.h>
#include <PCSC/wintypes.h>
#include <PCSC/winscard.h>


typedef unsigned int uint32_t;
#define PANIC 0
#define DONT_PANIC 1


#define SCARD_ATTR_ATR_STRING 590595

void test_rv(LONG rv, SCARDCONTEXT hContext, int dont_panic);
void test_rv(LONG rv, SCARDCONTEXT hContext, int dont_panic)
{
    if (rv != SCARD_S_SUCCESS)
    {
        if (dont_panic)
            printf( "%s (don't panic)\n" , pcsc_stringify_error(rv));
        else
        {
            printf( "%s\n" , pcsc_stringify_error(rv));
            SCardReleaseContext(hContext);
        }
    }
    else
        puts(pcsc_stringify_error(rv));
}

int main(int argc, char **argv)
{
    SCARDHANDLE hCard;
    SCARDCONTEXT hContext;
    SCARD_READERSTATE_A rgReaderStates[1];
    DWORD dwReaderLen, dwState, dwProt, dwAtrLen;
    DWORD dwPref, dwReaders = 0;
    char *pcReaders, *mszReaders;
    unsigned char pbAtr[MAX_ATR_SIZE];
    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;

    printf("\nMUSCLE PC/SC Lite unitary test Program\n\n");


    printf("Testing SCardEstablishContext\t: ");
    rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
    test_rv(rv, hContext, PANIC);

    printf("Testing SCardGetStatusChange \n");
    printf("Please insert a working reader\t: ");
    fflush(stdout);
    rv = SCardGetStatusChange(hContext, INFINITE, 0, 0);
    test_rv(rv, hContext, PANIC);

    printf("Testing SCardListReaderGroups\t: ");
    rv = SCardListReaderGroups(hContext, 0, &dwGroups);
    test_rv(rv, hContext, PANIC);

    printf("Testing SCardListReaderGroups\t: ");
    mszGroups = calloc(dwGroups, sizeof(char));
    rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
    test_rv(rv, hContext, PANIC);

    /*
     * Have to understand the multi-string here
     */
    p = 0;
    for (i = 0; i+1 < dwGroups; i++)
    {
        ++p;
        printf( "Group %02d: %s\n" , p, &mszGroups[i]);
        iList[p] = i;
        while (mszGroups[++i] != 0) ;
    }

wait_for_card_again:
    printf("Testing SCardListReaders\t: ");

    mszGroups = NULL;
    rv = SCardListReaders(hContext, mszGroups, 0, &dwReaders);
    test_rv(rv, hContext, PANIC);

    printf("Testing SCardListReaders\t: ");
    mszReaders = calloc(dwReaders, sizeof(char));
    rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);
    test_rv(rv, hContext, PANIC);

    /*
     * Have to understand the multi-string here
     */
    p = 0;
    for (i = 0; i+1 < dwReaders; i++)
    {
        ++p;
        printf( "Reader %02d: %s\n" , p, &mszReaders[i]);
        iList[p] = i;
        while (mszReaders[++i] != 0) ;
    }

    if (p > 1)
        do
        {
            char input[80];

            printf("Enter the reader number\t\t: ");
            fgets(input, sizeof(input), stdin);
            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: ");
    fflush(stdout);
    rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
    test_rv(rv, hContext, PANIC);
    if (SCARD_STATE_EMPTY == rgReaderStates[0].dwEventState)
    {
        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;
        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,
                       &pioRecvPci, bRecvBuffer, &length);
    printf("%s\n", pcsc_stringify_error(rv));
    printf(" card response:" );
    for (i=0; i<length; i++)
        printf(" %02X", bRecvBuffer[i]);
    printf("\n" );

    /* APDU ramdom */
    printf("Get 8 bytes Ramdom Number:");
    send_length = 5;
    memcpy(bSendBuffer, "\x00\x84\x00\x00\x08", 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,
                       &pioRecvPci, bRecvBuffer, &length);
    printf("%s\n", pcsc_stringify_error(rv));
    printf(" card response:" );
    for (i=0; i<length; i++)
        printf(" %02X", bRecvBuffer[i]);
    printf("\n" );



    printf("Testing SCardGetAttrib\t\t: ");
    rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &dwAtrLen);
    test_rv(rv, hContext, DONT_PANIC);
    if (rv == SCARD_S_SUCCESS)
        printf("SCARD_ATTR_ATR_STRING length: "  "%ld\n" , dwAtrLen);

    printf("Testing SCardGetAttrib\t\t: ");
    dwAtrLen = sizeof(pbAtr);
    rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAtr, &dwAtrLen);
    test_rv(rv, hContext, DONT_PANIC);
    if (rv == SCARD_S_SUCCESS)
    {
        printf("SCARD_ATTR_ATR_STRING: " );
        for (i = 0; i < dwAtrLen; i++)
            printf("%02X ", pbAtr[i]);
        printf("\n" );
    }


    printf("Testing SCardStatus\t\t: ");

    dwReaderLen = 100;
    pcReaders   = malloc(sizeof(char) * 100);
    dwAtrLen    = MAX_ATR_SIZE;

    rv = SCardStatus(hCard, pcReaders, &dwReaderLen, &dwState, &dwProt,
                     pbAtr, &dwAtrLen);
    test_rv(rv, hContext, PANIC);

    printf("Current Reader Name\t\t: "  "%s\n" , pcReaders);
    printf("Current Reader State\t\t: "  "0x%.4x\n" , dwState);
    printf("Current Reader Protocol\t\t: T="  "%u\n" , dwProt - 1);
    printf("Current Reader ATR Size\t\t: "  "%u"  " bytes\n",
           dwAtrLen);
    printf("Current Reader ATR Value\t: " );

    for (i = 0; i < dwAtrLen; i++)
    {
        printf("%02X ", pbAtr[i]);
    }
    printf( "\n");

    if (rv != SCARD_S_SUCCESS)
    {
        SCardDisconnect(hCard, SCARD_RESET_CARD);
        SCardReleaseContext(hContext);
    }


    //sleep(1);
    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);

    printf("Testing SCardReleaseContext\t: ");
    rv = SCardReleaseContext(hContext);
    test_rv(rv, hContext, PANIC);

    printf("\n");
    printf("PC/SC Test Completed Successfully !\n");

    return 0;
}

Delphi 7

Please check the whole source code in SDK

https://github.com/FeitianSmartcardReader/R301/tree/master/Demo

VB.NET

Please check the whole source code in SDK

https://github.com/FeitianSmartcardReader/R301/tree/master/Demo

JAVA

Please check the whole source code in SDK

https://github.com/FeitianSmartcardReader/R301/tree/master/Demo

GO

package main
import(
    "fmt"
    "github.com/ebfe/scard"
)
func main() {
    // Establish a PC/SC context
    context,
    err: = scard.EstablishContext()
    if err != nil {
        fmt.Println("Error EstablishContext:", err)
        return
    }
    // Release the PC/SC context (when needed)
    defer context.Release()
    // List available readers
    readers,
    err: = context.ListReaders()
    if err != nil {
        fmt.Println("Error ListReaders:", err)
        return
    }
    // Use the first reader
    reader: = readers[0]
    fmt.Println("Using reader:", reader)
    // Connect to the card
    card,
    err: = context.Connect(reader, scard.ShareShared, scard.ProtocolAny)
    if err != nil {
        fmt.Println("Error Connect:", err)
        return
    }
    // Disconnect (when needed)
    defer card.Disconnect(scard.LeaveCard)
    // Send select APDU
    var cmd_select = [] byte {
        0x00,
        0xa4,
        0x04,
        0x00,
        0x0A,
        0xA0,
        0x00,
        0x00,
        0x00,
        0x62,
        0x03,
        0x01,
        0x0C,
        0x06,
        0x01
    }
    rsp,
    err: = card.Transmit(cmd_select)
    if err != nil {
        fmt.Println("Error Transmit:", err)
        return
    }
    fmt.Println(rsp)
    // Send command APDU
    var cmd_command = [] byte { 0x00, 0x00, 0x00, 0x00 }
    rsp,
    err = card.Transmit(cmd_command)
    if err != nil {
        fmt.Println("Error Transmit:", err)
        return
    }
    fmt.Println(rsp)
    for i: = 0;i < len(rsp)‐ 2;i++{
        fmt.Printf("%c", rsp[i])
    }
    fmt.Println()
}

Python

from smartcard.scard
import *
import smartcard.util

SELECT = [0x00, 0xA4, 0x04, 0x00, 0x0A, 0xA0, 0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x0C, 0x06, 0x01]
COMMAND = [0x00, 0x00, 0x00, 0x00]

try:
    hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
    if hresult != SCARD_S_SUCCESS:
        raise Exception('Failed to establish context : ' + SCardGetErrorMessage(hresult))

print 'Context established!'

try:
    hresult, readers = SCardListReaders(hcontext, [])
    if hresult != SCARD_S_SUCCESS:
        raise Exception('Failed to list readers: ' + SCardGetErrorMessage(hresult))

print 'PCSC Readers:', readers

if len(readers) < 1:
    raise Exception('No smart card readers')

reader = readers[0]
print "Using reader:", reader

try:
    hresult, hcard, dwActiveProtocol = SCardConnect(hcontext, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
if hresult != SCARD_S_SUCCESS:
    raise Exception('Unable to connect: ' + SCardGetErrorMessage(hresult))
print 'Connected with active protocol', dwActiveProtocol

try:
    hresult, response = SCardTransmit(hcard, dwActiveProtocol, SELECT)
    if hresult != SCARD_S_SUCCESS:
           raise Exception('Failed to transmit: ' + SCardGetErrorMessage(hresult))
print 'Select: ' + smartcard.util.toHexString(response, smartcard.util.HEX)

hresult, response = SCardTransmit(hcard, dwActiveProtocol, COMMAND)
if hresult != SCARD_S_SUCCESS:
    raise Exception('Failed to transmit: ' + SCardGetErrorMessage(hresult))

print 'Command: ' + smartcard.util.toHexString(response, smartcard.util.HEX)

finally:
    hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD)
    if hresult != SCARD_S_SUCCESS:
        raise Exception('Failed to disconnect: ' + SCardGetErrorMessage(hresult))
print 'Disconnected'

except Exception, message:
print "Exception:", message

finally:
    hresult = SCardReleaseContext(hcontext)

if hresult != SCARD_S_SUCCESS:
    raise Exception('Failed to release context: ' + SCardGetErrorMessage(hresult))

print 'Released context.'
except Exception, message:

C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Simple_PCSC
{
    public partial class Simple_PCSC : Form
    {
        uint PRT;
        int ATRLen, ReaderLen, dwState;
        byte[] ATR = new byte[33];
        SCARD_IO_REQUEST IORequest;
        public int hCard, hContext;                     // hContext=10
        public int Protocol, ReaderCount;
        public string CardReaderDesc = "";              // Save the device descriptor string

        public Simple_PCSC()
        {
            InitializeComponent();
        }


        // Byte[] to HexString
        static char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        public static string ToHexString(byte[] bytes, int BytesLength)
        {
            char[] chars = new char[bytes.Length * 5];
            for (int i = 0; i < BytesLength; i++)
            {
                int b = bytes[i];
                chars[i * 3 + 0] = hexDigits[b >> 4];
                chars[i * 3 + 1] = hexDigits[b & 0xF];
                chars[i * 3 + 2] = ' ';
            }
            return new string(chars);
        }

        // HexString to Byte[]
        private static byte[] ToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[(hexString.Length / 2)];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);

            return returnBytes;
        }

        void DisplayOut(int mType, long msgCode, string PrintText)
        {
            switch (mType)
            {
                case 0:                                  // Notifications only
                    mMsg.SelectionColor = Color.Green;
                    break;
                case 1:                                  // Error Messages
                    mMsg.SelectionColor = Color.Red;
                    PrintText = ModWinsCard.GetScardErrMsg((int)msgCode);
                    break;
                case 2:                                  // Input data
                    mMsg.SelectionColor = Color.Black;
                    PrintText = "< " + PrintText;
                    break;
                case 3:                                  // Output data
                    mMsg.SelectionColor = Color.Black;
                    PrintText = "> " + PrintText;
                    break;
                case 4:                                  // Critical Errors
                    mMsg.SelectionColor = Color.Red;
                    break;
            }

            mMsg.SelectedText = PrintText + "\n";
            mMsg.SelectionStart = mMsg.Text.Length;
            mMsg.SelectionColor = Color.Black;
        }

        private bool ListCardReaderDesc()
        {
            int RetListCardReader;
            int PccHReaders = 0;


            //Establish Context
            RetListCardReader = ModWinsCard.SCardEstablishContext(ModWinsCard.SCARD_SCOPE_USER, 0, 0, ref hContext);

            if (RetListCardReader != ModWinsCard.SCARD_S_SUCCESS)
            {
                return false;
            }

            // 2. List PC/SC card readers installed in the system
            RetListCardReader = ModWinsCard.SCardListReaders(hContext, null, null, ref PccHReaders);

            if (RetListCardReader != ModWinsCard.SCARD_S_SUCCESS)
            {
                return false;
            }

            string ReaderList = "" + Convert.ToChar(0);
            int Index;
            string ReaderName = "";
            ReaderName = "";
            Index = 0;
            PccHReaders = 255;
            byte[] ReadersList = new byte[PccHReaders];

            // Fill reader list
            RetListCardReader = ModWinsCard.SCardListReaders(hContext, null, ReadersList, ref PccHReaders);

            if (RetListCardReader != ModWinsCard.SCARD_S_SUCCESS)
            {
                return false;
            }
            if (CardReaderDesc == "")
            {
                ReaderListComboBox.Items.Clear();
            }
            //Convert reader buffer to string
            while (ReadersList[Index] != 0)
            {

                while (ReadersList[Index] != 0)
                {
                    ReaderName = ReaderName + (char)ReadersList[Index];
                    Index = Index + 1;
                }

                if (CardReaderDesc == "")
                {
                    //Add reader name to list
                    //  if (string.Compare(ReaderName, bR301_ReaderName) == 0)
                    {
                        ReaderListComboBox.Items.Add(ReaderName);
                    }
                }
                else
                {
                    if (string.Compare(ReaderName, CardReaderDesc) == 0)
                    {
                        return true;
                    }
                    else
                    {
                        ReaderListComboBox.Items.Clear();
                        ReaderListComboBox.Items.Add(ReaderName);
                        return true;
                    }
                }
                ReaderName = "";
                Index = Index + 1;
            }
            return true;
        }

        private void ReaderInitButton_Click(object sender, EventArgs e)
        {
            ReaderListComboBox.Items.Clear();
            ReaderListComboBox.Text = "";
            CardReaderDesc = "";


            if (ListCardReaderDesc())
            {
                ReaderListComboBox.SelectedIndex = 0;
                DisplayOut(0, 0, "SCardListReaders... OK");
                ReaderConnectButton.Enabled = true;
                StartPpollingButton.Enabled = true;
                StopPpollingButton.Enabled = true;

                ReaderReleaseContextbutton.Enabled = true;
            }
            else
            {
                DisplayOut(4, 0, "SCardListReaders... ERR");
            }

        }

        private void ReaderConnectButton_Click(object sender, EventArgs e)
        {
            CardReaderDesc = ReaderListComboBox.SelectedItem.ToString();

            // Don't use SCARD_SHARE_DIRECT , After Ppolling the transmit return 0x00000016 Unknown Error
            int retCode = ModWinsCard.SCardConnect(this.hContext, CardReaderDesc, ModWinsCard.SCARD_SHARE_SHARED,
                                                    ModWinsCard.SCARD_PROTOCOL_T0 | ModWinsCard.SCARD_PROTOCOL_T1, ref hCard, ref Protocol);

            if (retCode != ModWinsCard.SCARD_S_SUCCESS)
                DisplayOut(1, retCode, "");

            else
            {
                DisplayOut(0, 0, "SCardConnect...OK");
                ReaderConnectButton.Enabled = false;
                StartPpollingButton.Enabled = false;
                StopPpollingButton.Enabled = false;

                ReaderTransmitButton.Enabled = true;
                ReaderDisconnectButton.Enabled = true;
                ReaderReleaseContextbutton.Enabled = true;
                ReaderStatusButton.Enabled = true;
            }
        }

        private void ReaderTransmitButton_Click(object sender, EventArgs e)
        {
            if (m_Apdu.Text == "")
            {
                DisplayOut(4, 0, "No data input");
                return;
            }

            m_Apdu.Text = (m_Apdu.Text.Replace(" ", ""));
            if (m_Apdu.Text.Length < 10)
            {
                DisplayOut(4, 0, "Insufficient data input");
                return;
            }

            if ((m_Apdu.Text.Length % 2) != 0)
            {
                DisplayOut(4, 0, "Invalid data input, uneven number of characters");
                m_Apdu.Focus();
                return;
            }

            byte[] SendBuff = new byte[1024];
            byte[] RecvBuff = new byte[1024];
            int SendLen = 1024;
            int RecvLen = 1024;

            SendLen = m_Apdu.Text.Length / 2;
            byte[] tempBuff = ToHexByte(m_Apdu.Text);
            Array.Copy(tempBuff, SendBuff, SendLen);

            IORequest.dwProtocol = Protocol;
            IORequest.cbPciLength = 8;
            int retCode = ModWinsCard.SCardTransmit(hCard, ref IORequest, ref SendBuff[0], SendLen, ref IORequest, ref RecvBuff[0], ref RecvLen);
            if (retCode != ModWinsCard.SCARD_S_SUCCESS)
            {
                DisplayOut(1, retCode, "");
            }
            else
            {
                string tempStr = ToHexString(RecvBuff, RecvLen);
                DisplayOut(0, 0, tempStr);
            }
        }

        private void ReaderDisconnectButton_Click(object sender, EventArgs e)
        {
            int retCode = ModWinsCard.SCardDisconnect(hCard, ModWinsCard.SCARD_UNPOWER_CARD);

            if (retCode != ModWinsCard.SCARD_S_SUCCESS)
                DisplayOut(1, retCode, "");
            else
            {
                DisplayOut(0, 0, "SCardDisconnect...OK");
                ReaderConnectButton.Enabled = true;
                StartPpollingButton.Enabled = true;
                StopPpollingButton.Enabled = true;

                ReaderStatusButton.Enabled = false;
                ReaderTransmitButton.Enabled = false;
                ReaderDisconnectButton.Enabled = false;
            }
        }

        private void ReaderReleaseContextbutton_Click(object sender, EventArgs e)
        {
            CardReaderDesc = "";
            int retCode = ModWinsCard.SCardReleaseContext(hContext);

            if (retCode != ModWinsCard.SCARD_S_SUCCESS)
                DisplayOut(1, retCode, "");
            else
            {
                DisplayOut(0, 0, "SCardReleaseContext...OK");

                ReaderConnectButton.Enabled = false;
                StartPpollingButton.Enabled = false;
                StopPpollingButton.Enabled = false;

                ReaderTransmitButton.Enabled = false;
                ReaderDisconnectButton.Enabled = false;
                ReaderReleaseContextbutton.Enabled = false;
                ReaderStatusButton.Enabled = false;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            // perform if the card is inserted/not inserted on the reader 

            // Don't connection before to connect card reader.
            // If the connection card reader to make a card, and after make smart card device manager to suspend work, and can't get correct card slots.
            SCARD_READERSTATE ReaderState = new SCARD_READERSTATE();
            ReaderState.RdrName = ReaderListComboBox.SelectedItem.ToString();

            mMsg.Clear();

            int retCode = ModWinsCard.SCardGetStatusChange(this.hContext, -1, ref ReaderState, 1);
            if (retCode != ModWinsCard.SCARD_S_SUCCESS)
            {
                DisplayOut(1, retCode, "");
            }
            else
            {
                if ((ReaderState.RdrEventState & ModWinsCard.SCARD_STATE_PRESENT) != 0)
                {
                    DisplayOut(0, 0, "Card Inserted");
                }
                else
                {
                    DisplayOut(0, 0, "Card Removed");
                }
            }
        }

        private void StartPpollingButton_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;
            ReaderConnectButton.Enabled = false;
            StartPpollingButton.Enabled = false;
            ReaderReleaseContextbutton.Enabled = false;
        }

        private void StopPpollingButton_Click(object sender, EventArgs e)
        {
            StartPpollingButton.Enabled = true;
            ReaderConnectButton.Enabled = true;
            ReaderReleaseContextbutton.Enabled = true;
            timer1.Enabled = false;
            DisplayOut(0, 0, "Stop Ppolling");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            short index;
            string Temp;
            ATRLen = 33;
            CardReaderDesc = ReaderListComboBox.SelectedItem.ToString();

            //perform the Card Status
            int retcode = ModWinsCard.SCardStatus(this.hCard, CardReaderDesc, ref ReaderLen, ref dwState, ref Protocol, ref ATR[0], ref ATRLen);

            if (retcode != ModWinsCard.SCARD_S_SUCCESS)
            {
                DisplayOut(1, retcode, "");
            }
            else
            {
                DisplayOut(0, 0, "SCardStatus OK...");

                // select for the protocol
                switch (Protocol)
                {
                    case 0: PRT = ModWinsCard.SCARD_PROTOCOL_UNDEFINED;
                        DisplayOut(0, 0, "Active Protocol Undefined");
                        break;
                    case 1: PRT = ModWinsCard.SCARD_PROTOCOL_T0;
                        DisplayOut(0, 0, "Active Protocol T0");
                        break;
                    case 2: PRT = ModWinsCard.SCARD_PROTOCOL_T1;
                        DisplayOut(0, 0, "Active Protocol T1");
                        break;
                }

                Temp = "ATR:";

                for (index = 0; index < ATRLen; index++)
                    Temp = Temp + " " + string.Format("{0:X2}", ATR[index]);

                // Display ATR value 
                DisplayOut(0, 0, Temp);
            }
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            mMsg.Clear();
        }
    }
}