Fix Card UID retrieval for Raspberry PI/linux systems.
It appears that the issue was also relevant to windows, but windows somehow compensated? #103
This commit is contained in:
parent
b557174ef9
commit
9f617fdf0a
@ -38,8 +38,8 @@
|
|||||||
<HintPath>..\packages\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="pcsc-sharp, Version=3.6.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="PCSC, Version=4.2.0.0, Culture=neutral, PublicKeyToken=13b76e54a2ee80a7, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\PCSC.3.6.0\lib\net40\pcsc-sharp.dll</HintPath>
|
<HintPath>..\packages\PCSC.4.2.0\lib\net40\PCSC.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
using PCSC;
|
using PCSC;
|
||||||
using System;
|
using System;
|
||||||
|
using System.CodeDom;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Logger;
|
using Logger;
|
||||||
|
using PCSC.Monitoring;
|
||||||
|
|
||||||
namespace CardReaderService
|
namespace CardReaderService
|
||||||
{
|
{
|
||||||
@ -13,10 +15,9 @@ namespace CardReaderService
|
|||||||
{
|
{
|
||||||
private Thread _mainWorkThread;
|
private Thread _mainWorkThread;
|
||||||
private bool _stopMainWorkerThread;
|
private bool _stopMainWorkerThread;
|
||||||
private AutoResetEvent _mainWorkerTerminationSignal;
|
|
||||||
private string _readerName = "";
|
private string _readerName = string.Empty;
|
||||||
private SCardMonitor _cardMonitor;
|
private SCardMonitor _cardMonitor;
|
||||||
private bool _initialised=false;
|
|
||||||
|
|
||||||
public Service1()
|
public Service1()
|
||||||
{
|
{
|
||||||
@ -28,65 +29,53 @@ namespace CardReaderService
|
|||||||
OnStart(new string[] { });
|
OnStart(new string[] { });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public new void Stop()
|
||||||
|
{
|
||||||
|
OnStop();
|
||||||
|
base.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnStart(string[] args)
|
protected override void OnStart(string[] args)
|
||||||
{
|
{
|
||||||
<<<<<<< HEAD
|
MessageLogger.Log("Starting.. ");
|
||||||
StartWorkerThread();
|
|
||||||
}
|
|
||||||
=======
|
|
||||||
Console.WriteLine("Starting.. Getting available readers");
|
|
||||||
MessageLogger.Log("Starting.. Getting available readers");
|
|
||||||
var ctxFactory = ContextFactory.Instance;
|
var ctxFactory = ContextFactory.Instance;
|
||||||
using(var context = ctxFactory.Establish(SCardScope.System))
|
using (var context = ctxFactory.Establish(SCardScope.System))
|
||||||
{
|
{
|
||||||
|
MessageLogger.Log("Getting Card Readers");
|
||||||
var readerNames = context.GetReaders();
|
var readerNames = context.GetReaders();
|
||||||
if (NoReaderAvailable(readerNames))
|
if (NoReaderAvailable(readerNames))
|
||||||
{
|
{
|
||||||
Console.WriteLine("No Card Reader is available, Exiting..");
|
MessageLogger.Log("No Card Reader available, Exiting..");
|
||||||
MessageLogger.Log("No Card Reader is available, Exiting..");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
Console.WriteLine("Choosing first available reader: " + readerNames.First());
|
else
|
||||||
|
{
|
||||||
MessageLogger.Log("Choosing first available reader: " + readerNames.First());
|
MessageLogger.Log("Choosing first available reader: " + readerNames.First());
|
||||||
_readerName = readerNames.First();
|
_readerName = readerNames.First();
|
||||||
_cardMonitor = new SCardMonitor(ctxFactory, SCardScope.System);
|
_cardMonitor = new SCardMonitor(ctxFactory, SCardScope.System);
|
||||||
_cardMonitor.CardInserted += _cardMonitor_CardInserted;
|
_cardMonitor.CardInserted += CardMonitor_CardInserted;
|
||||||
|
_cardMonitor.StatusChanged += CardMonitorOnStatusChanged;
|
||||||
_cardMonitor.Start(_readerName);
|
_cardMonitor.Start(_readerName);
|
||||||
>>>>>>> retarget for .net 4.5 (from 4.5.2) for mono support.
|
|
||||||
|
|
||||||
private bool WeHaveValidCardReader()
|
|
||||||
{
|
|
||||||
if (_cardMonitor == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
Console.WriteLine(_cardMonitor.GetCurrentState(0));
|
StartWorkerThread();
|
||||||
if (_cardMonitor.GetCurrentState(0) == SCRState.Unknown
|
|
||||||
|| _cardMonitor.GetCurrentState(0) == SCRState.Unavailable
|
|
||||||
|| _cardMonitor.GetCurrentState(0) == (SCRState.Ignore | SCRState.Unavailable)
|
|
||||||
//|| _cardMonitor.GetCurrentState(0) == SCRState.Unaware //if we say this is an invalid state, we cause a memory leak where we create a duplicate card monitor, subscribe and overwrite.
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
OnStop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnStop()
|
protected override void OnStop()
|
||||||
{
|
{
|
||||||
|
MessageLogger.Log("Stopping..");
|
||||||
_stopMainWorkerThread = true;
|
_stopMainWorkerThread = true;
|
||||||
_mainWorkerTerminationSignal.Set();
|
|
||||||
if (_mainWorkThread != null && _mainWorkThread.IsAlive)
|
if (_mainWorkThread != null && _mainWorkThread.IsAlive)
|
||||||
|
{
|
||||||
|
_mainWorkThread.Join(3000);
|
||||||
|
if (_mainWorkThread.IsAlive)
|
||||||
{
|
{
|
||||||
_mainWorkThread.Interrupt();
|
_mainWorkThread.Interrupt();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (_cardMonitor != null)
|
if (_cardMonitor != null)
|
||||||
{
|
{
|
||||||
|
_cardMonitor.CardInserted -= CardMonitor_CardInserted;
|
||||||
|
_cardMonitor.StatusChanged -= CardMonitorOnStatusChanged;
|
||||||
_cardMonitor.Cancel();
|
_cardMonitor.Cancel();
|
||||||
_cardMonitor.Dispose();
|
_cardMonitor.Dispose();
|
||||||
_cardMonitor = null;
|
_cardMonitor = null;
|
||||||
@ -101,96 +90,101 @@ namespace CardReaderService
|
|||||||
Name = "CardServiceMainThread",
|
Name = "CardServiceMainThread",
|
||||||
IsBackground = false
|
IsBackground = false
|
||||||
};
|
};
|
||||||
_mainWorkerTerminationSignal = new AutoResetEvent(false);
|
|
||||||
_mainWorkThread.Start();
|
_mainWorkThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _cardMonitor_CardInserted(object sender, CardStatusEventArgs e)
|
private void CardMonitor_CardInserted(object sender, CardStatusEventArgs e)
|
||||||
{
|
{
|
||||||
var ctxFac = ContextFactory.Instance;
|
var ctxFac = ContextFactory.Instance;
|
||||||
using (var ctx = ctxFac.Establish(SCardScope.System))
|
using (var ctx = ctxFac.Establish(SCardScope.System))
|
||||||
{
|
{
|
||||||
var reader = new SCardReader(ctx);
|
var reader = new SCardReader(ctx);
|
||||||
var pioSendPci = new IntPtr();
|
|
||||||
byte[] rcvBuffer = new byte[256];
|
byte[] rcvBuffer = new byte[256];
|
||||||
|
|
||||||
if (_readerName == string.Empty)
|
if (_readerName == string.Empty)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Reader name is somehow empty... WTF!");
|
MessageLogger.Log("Reader name is somehow empty... WTF!");
|
||||||
_stopMainWorkerThread = true;
|
_stopMainWorkerThread = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var err = reader.Connect(_readerName, SCardShareMode.Shared, SCardProtocol.T0 | SCardProtocol.T1);
|
var err = reader.Connect(_readerName, SCardShareMode.Shared, SCardProtocol.Any);
|
||||||
|
|
||||||
if (err == SCardError.Success)
|
if (err == SCardError.Success)
|
||||||
{
|
{
|
||||||
var uIdcmd = new byte[] { 0xFF, 0xCA, 0x00, 0x00, 0x00 };
|
var pci = SCardPCI.GetPci(reader.ActiveProtocol);
|
||||||
|
|
||||||
|
err = reader.Transmit(pci, CardCommands.GetUid, ref rcvBuffer);
|
||||||
|
|
||||||
err = reader.Transmit(pioSendPci, uIdcmd, ref rcvBuffer);
|
|
||||||
if (err == SCardError.Success)
|
if (err == SCardError.Success)
|
||||||
{
|
{
|
||||||
var uid = ConvertByteUIDToString(rcvBuffer);
|
var uid = ConvertByteUIDToString(rcvBuffer);
|
||||||
var atrString = ConvertByteUIDToString(e.Atr);
|
var atrString = ConvertByteUIDToString(e.Atr);
|
||||||
Console.WriteLine("Card Inserted, ATR: " + atrString + ", and UID is: " + uid);
|
|
||||||
|
|
||||||
CardDataPost postObj = new CardDataPost { CardUId = uid };
|
MessageLogger.Log("Card Inserted, ATR: " + atrString + ", and UID is: " + uid);
|
||||||
|
|
||||||
|
CardDataPost postObj = new CardDataPost { CardUId = uid, UtcTimeStamp = DateTime.UtcNow};
|
||||||
DataCenterHelper.PostAsync(postObj, "/api/swipedata");
|
DataCenterHelper.PostAsync(postObj, "/api/swipedata");
|
||||||
Console.WriteLine("Posted to Server");
|
MessageLogger.Log("Posted to Server");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageLogger.Log("Failed to Read UID, Error: "+ err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Reader failed to connect, error: " + Enum.GetName(typeof(SCardError), err));
|
MessageLogger.Log("Reader failed to connect, error: " + Enum.GetName(typeof(SCardError), err));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MainWorkerThread()
|
private void MainWorkerThread()
|
||||||
{
|
{
|
||||||
|
var minimumLoopTimemS = 5000;
|
||||||
|
|
||||||
while (!_stopMainWorkerThread)
|
while (!_stopMainWorkerThread)
|
||||||
{
|
{
|
||||||
if (!WeHaveValidCardReader())
|
if (_cardMonitor == null)
|
||||||
{ //only do this if we don't have a valid card reader
|
|
||||||
if (_initialised)
|
|
||||||
{
|
{
|
||||||
//card reader no longer available, tidy up.
|
|
||||||
_cardMonitor.Cancel();
|
|
||||||
_cardMonitor.CardInserted -= _cardMonitor_CardInserted;
|
|
||||||
_cardMonitor.Dispose();
|
|
||||||
_cardMonitor = null;
|
|
||||||
_initialised = false;
|
|
||||||
}
|
|
||||||
Console.WriteLine("Starting.. Getting available readers");
|
|
||||||
var ctxFactory = ContextFactory.Instance;
|
var ctxFactory = ContextFactory.Instance;
|
||||||
using (var context = ctxFactory.Establish(SCardScope.System))
|
using (var context = ctxFactory.Establish(SCardScope.System))
|
||||||
{
|
{
|
||||||
var readerNames = context.GetReaders();
|
var readerNames = context.GetReaders();
|
||||||
if (!NoReaderAvailable(readerNames))
|
if (NoReaderAvailable(readerNames))
|
||||||
{
|
{
|
||||||
//we have a reader available, so initialise!
|
MessageLogger.Log("No Card Reader available, Waiting..");
|
||||||
Console.WriteLine("Choosing first available reader: " + readerNames.First());
|
|
||||||
_readerName = readerNames.First();
|
|
||||||
_cardMonitor = new SCardMonitor(ctxFactory, SCardScope.System);
|
|
||||||
_cardMonitor.CardInserted += _cardMonitor_CardInserted;
|
|
||||||
_cardMonitor.Start(_readerName);
|
|
||||||
|
|
||||||
_initialised = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("No Card Reader is available..");
|
MessageLogger.Log("Choosing first available reader: " + readerNames.First());
|
||||||
|
_readerName = readerNames.First();
|
||||||
|
_cardMonitor = new SCardMonitor(ctxFactory, SCardScope.System);
|
||||||
|
_cardMonitor.CardInserted += CardMonitor_CardInserted;
|
||||||
|
_cardMonitor.StatusChanged += CardMonitorOnStatusChanged;
|
||||||
|
_cardMonitor.Start(_readerName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_mainWorkerTerminationSignal.WaitOne(3000);
|
//dont actually need to do anything.. but cannot exit right away?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CardMonitorOnStatusChanged(object sender, StatusChangeEventArgs e)
|
||||||
|
{
|
||||||
|
if ((e.NewState & SCRState.Unavailable) == SCRState.Unavailable && (e.NewState & SCRState.Ignore) == SCRState.Ignore)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Card Reader Disconnected");
|
||||||
|
_cardMonitor.CardInserted -= CardMonitor_CardInserted;
|
||||||
|
_cardMonitor.Cancel();
|
||||||
|
_cardMonitor.Dispose();
|
||||||
|
_cardMonitor = null;
|
||||||
|
_readerName = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ConvertByteUIDToString(byte[] uid)
|
private string ConvertByteUIDToString(byte[] uid)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
foreach (var b in uid)
|
foreach (var b in uid)
|
||||||
{
|
{
|
||||||
@ -205,4 +199,9 @@ namespace CardReaderService
|
|||||||
return readerNames == null || readerNames.Count < 1;
|
return readerNames == null || readerNames.Count < 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class CardCommands
|
||||||
|
{
|
||||||
|
public static readonly byte[] GetUid = {0xFF, 0xCA, 0x00, 0x00, 0x08};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="10.0.1" targetFramework="net45" />
|
<package id="Newtonsoft.Json" version="10.0.1" targetFramework="net45" />
|
||||||
<package id="PCSC" version="3.6.0" targetFramework="net45" />
|
<package id="PCSC" version="4.2.0" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
||||||
@ -34,8 +34,8 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>..\CardReaderService\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
|||||||
@ -9,7 +9,7 @@ namespace CardReaderServiceHost
|
|||||||
{
|
{
|
||||||
Service1 service1 = new Service1();
|
Service1 service1 = new Service1();
|
||||||
service1.Start();
|
service1.Start();
|
||||||
Console.WriteLine("Service Running...");
|
Console.WriteLine("Service Running... Enter To Stop");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
service1.Stop();
|
service1.Stop();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
<package id="Newtonsoft.Json" version="10.0.1" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
||||||
@ -13,6 +13,7 @@ namespace Logger
|
|||||||
|
|
||||||
public static void Log(string message)
|
public static void Log(string message)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine(message);
|
||||||
System.IO.File.WriteAllText(_logPath, string.Format("{0} | {1}", DateTime.Now, message));
|
System.IO.File.WriteAllText(_logPath, string.Format("{0} | {1}", DateTime.Now, message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user