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();
}
}
}