Right so I have the following code that works fine using the PCSC-sharp Iso7816 Library:
Imports PCSC
Imports PCSC.Iso7816
Imports PCSC.Utils
Imports System
Public Class TapMembershipCard
Dim MembershipCardUID As String
Sub ReadCard() Handles ReadCardBtn.Click
Using context = New SCardContext()
context.Establish(SCardScope.System)
Dim readerNames = context.GetReaders()
Dim sc As PCSC.SCardError
Dim readerName = readerNames.FirstOrDefault()
If readerName Is Nothing Then
Return
End If
Using rfidReader = New SCardReader(context)
sc = rfidReader.Connect(readerName, SCardShareMode.Shared, SCardProtocol.Any)
If sc <> SCardError.Success Then
'THIS IS USUALLY WHERE THE PROGRAM WILL GET TO IF NO CARD HAS BEEN PRESENTED
Return
End If
PresentCard.Visibility = Visibility.Hidden
Dim apdu = New CommandApdu(IsoCase.Case2Short, rfidReader.ActiveProtocol) With {
.CLA = &HFF,
.Instruction = InstructionCode.GetData,
.P1 = &H0,
.P2 = &H0,
.Le = 7
}
sc = rfidReader.BeginTransaction()
If sc <> SCardError.Success Then
Console.WriteLine("Could not begin transaction.")
Return
End If
Console.WriteLine("Retrieving the UID .... ")
Dim receivePci = New SCardPCI() ' IO returned protocol control information.
Dim sendPci = SCardPCI.GetPci(rfidReader.ActiveProtocol)
Dim receiveBuffer = New Byte(255) {}
Dim command = apdu.ToArray()
sc = rfidReader.Transmit(sendPci, command, receivePci, receiveBuffer)
If sc <> SCardError.Success Then
Console.WriteLine("Error: " & SCardHelper.StringifyError(sc))
End If
Dim responseApdu = New ResponseApdu(receiveBuffer, IsoCase.Case2Short, rfidReader.ActiveProtocol)
Console.Write("SW1: {0:X2}, SW2: {1:X2}" & vbCrLf & "Uid: {2}", responseApdu.SW1, responseApdu.SW2, If(responseApdu.HasData, BitConverter.ToString(responseApdu.GetData()), "No uid received"))
rfidReader.EndTransaction(SCardReaderDisposition.Leave)
rfidReader.Disconnect(SCardReaderDisposition.Reset)
MembershipCardUID = BitConverter.ToString(responseApdu.GetData())
End Using
End Using
End Sub
End Class
But ideally I would like to have it so that it constantly checks if a card is present instead of having to click the button once a card is presented. Also, can it be simplified in any way? I feel as though its a lot of code for just reading the UID.
I am willing to use any libraries or frameworks that are compatible with VB.net and also I'm happy for any ideas to be written in C# if it's preferred. FYI I'm using .NET 8.0 WPF Application. The reader is an ACR122U reader
I have tried to simply use recursion or call the sub again from within this IF statement:
sc = rfidReader.Connect(readerName, SCardShareMode.Shared, SCardProtocol.Any)
If sc <> SCardError.Success Then
'THIS IS USUALLY WHERE THE PROGRAM WILL GET TO IF NO CARD HAS BEEN PRESENTED
Return
End If
The issue is that none of the visual elements load / everything will freeze whilst it is constantly iterating until a card is presented.
Ideally I would like to be able to have some code that detects when a card is presented, then sends the ADPU command to retrieve the UID.
I ended up using the ACR122U Library Here's the documentation: Github + Website. It doesn't seem to be maintained but it is very helpful. Here's the code I ended up using (It is by no means perfect, its a work in progress. I have just managed to get the following working):