diff --git a/Borepin.sln b/Borepin.sln
index dda3f6a..da929dd 100644
--- a/Borepin.sln
+++ b/Borepin.sln
@@ -15,7 +15,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.GTK", "Borepin\Bore
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.macOS", "Borepin\Borepin.macOS\Borepin.macOS.csproj", "{3EC23FE7-395E-4BBC-B56B-9455354BDA34}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFC", "NFC\NFC.csproj", "{72DAC306-D4B2-4DBF-9C32-317203FD5D61}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NFC", "NFC\NFC.csproj", "{72DAC306-D4B2-4DBF-9C32-317203FD5D61}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFC_Test", "NFC_Test\NFC_Test.csproj", "{0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -249,6 +251,30 @@ Global
{72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x64.Build.0 = Release|Any CPU
{72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x86.ActiveCfg = Release|Any CPU
{72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x86.Build.0 = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|ARM.Build.0 = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x64.Build.0 = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x86.Build.0 = Debug|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|ARM.ActiveCfg = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|ARM.Build.0 = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhone.Build.0 = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x64.ActiveCfg = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x64.Build.0 = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x86.ActiveCfg = Release|Any CPU
+ {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/NFC/APDUCommand.cs b/NFC/APDUCommand.cs
new file mode 100644
index 0000000..c568298
--- /dev/null
+++ b/NFC/APDUCommand.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NFC
+{
+ public class APDUCommand
+ {
+ ///
+ /// ISO 7816 - CLA - Class
+ ///
+ public byte Class { get; set; }
+
+ ///
+ /// ISO 7816 - INS - Instruction
+ ///
+ public byte Instruction { get; set; }
+
+ ///
+ /// ISO 7816 - P1 - Parameter 1
+ ///
+ public byte Parameter1 { get; set; }
+
+ ///
+ /// ISO 7816 - P2 - Parameter 2
+ ///
+ public byte Parameter2 { get; set; }
+
+ ///
+ /// ISO 7816 - Lc - Length Command
+ ///
+ public byte LengthCommand
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ ///
+ /// ISO 7816 - Data - Data
+ ///
+ public byte[] Data { get; set; }
+
+ ///
+ /// ISO 7816 - Le - Length expected
+ ///
+ public byte LengthExpected
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public byte[] APDUCommandMessage()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/NFC/APDUResponse.cs b/NFC/APDUResponse.cs
new file mode 100644
index 0000000..bc4f810
--- /dev/null
+++ b/NFC/APDUResponse.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Linq;
+using NFC.Mifare_DESFire;
+
+namespace NFC
+{
+ public class APDUResponse
+ {
+ ///
+ /// ISO 7816 - Body - Body
+ ///
+ public byte[] Body { get; set; }
+
+ ///
+ /// ISO 7816 - SW1 - Status Word 1
+ ///
+ public byte SW1 { get; set; }
+
+ ///
+ /// ISO 7816 - SW2 - Status Word 2
+ ///
+ public byte SW2 { get; set; }
+
+ ///
+ /// Creates a new APDUResponse from the raw received data.
+ ///
+ public APDUResponse(byte[] raw) {
+ Body = raw.Take(raw.Length-1).ToArray();
+ SW1 = raw[raw.Length - 2];
+ SW2 = raw[raw.Length - 3];
+ }
+
+ public APDUResponse()
+ {
+
+ }
+
+ public APDUStatusWords StatusWord
+ {
+ get
+ {
+ // Some status words only require a specific first byte
+ // and in some cases SW2 contains additional information.
+ // This will filter out those errors. When there is more information separate methods for getting those are available.
+ switch(SW1) {
+ case 0x61:
+ // Kommando erfolgreich ausgeführt. xx Datenbytes können mit dem ‚GET RESPONSE‘-Kommando abgeholt werden. Statuswort zur Steuerung des T=0-Protokolls
+ return APDUStatusWords.DATA_READY;
+ case 0x62:
+ // Warnung; Zustand des nichtflüchtigen Speichers nicht verändert
+ return APDUStatusWords.STORAGE_NOT_CHANGED;
+ case 0x63:
+ if((SW2 & 0xF0) == 0xC0) {
+ // Zähler hat den Wert x erreicht (die genaue Bedeutung ist vom Kommando abhängig)
+ return APDUStatusWords.COUNTER_REACHED;
+ }
+ // Warnung; Zustand des nichtflüchtigen Speichers verändert
+ return APDUStatusWords.STORAGE_CHANGED;
+ case 0x64:
+ // Ausführungsfehler; Zustand des nichtflüchtigen Speichers nicht verändert
+ return APDUStatusWords.EXECUTION_ERROR_WITHOUT_CHANGE;
+ case 0x65:
+ // Ausführungsfehler; Zustand des nichtflüchtigen Speichers verändert
+ return APDUStatusWords.EXECUTION_ERROR_WITH_CHANGE;
+ case 0x6C:
+ // Falsche Länge Le; xx gibt die korrekte Länge an Statuswort zur Steuerung des T=0-Protokolls
+ return APDUStatusWords.INVALID_LE;
+ }
+ return (APDUStatusWords) (((UInt16) SW1) << 8 | ((UInt16) SW2));
+ }
+ }
+
+ ///
+ /// If the reponse status is DATA_READY this method can be used to get the amount of data that can be read from the card.
+ ///
+ public byte DataLength
+ {
+ get
+ {
+ return SW2;
+ }
+ }
+
+ ///
+ /// If the reponse status is COUNTER_REACHED this method can be used to get the value that the counter reached.
+ ///
+ public byte Counter
+ {
+ get
+ {
+ return (byte)(SW2 & 0x0F);
+ }
+ }
+
+ ///
+ /// If the reponse status is INVALID_LE this method can be used to get the correct LE.
+ ///
+ public byte CorrectLE
+ {
+ get
+ {
+ return SW2;
+ }
+ }
+ }
+}
diff --git a/NFC/APDUStatusWords.cs b/NFC/APDUStatusWords.cs
new file mode 100644
index 0000000..b0680cd
--- /dev/null
+++ b/NFC/APDUStatusWords.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NFC.Mifare_DESFire
+{
+ public enum APDUStatusWords : UInt16
+ {
+ ///
+ /// Kommando erfolgreich ausgeführt. xx Datenbytes können mit dem ‚GET RESPONSE‘-Kommando abgeholt werden. Statuswort zur Steuerung des T=0-Protokolls
+ ///
+ DATA_READY = 0x6100,
+
+ ///
+ /// Die zurückgegebenen Daten können fehlerhaft sein.
+ ///
+ FAULTY_DATA = 0x6281,
+
+ ///
+ /// Da das Dateiende vorher erreicht wurde, konnten nur weniger als Le Bytes gelesen werden.
+ ///
+ UNEXPECTED_END_OF_FILE = 0x6282,
+
+ ///
+ /// Die ausgewählte Datei ist gesperrt (englisch invalidated, wörtlich „ungültig“).
+ ///
+ INVALIDATED_FILE = 0x6283,
+
+ ///
+ /// Die File Control Information (FCI) ist inkonform zu ISO 7816-4.
+ ///
+ FCI_NOT_CONFORM = 0x6284,
+
+ ///
+ /// Warnung; Zustand des nichtflüchtigen Speichers nicht verändert
+ ///
+ STORAGE_NOT_CHANGED = 0x6200,
+
+ ///
+ /// Zähler hat den Wert x erreicht (die genaue Bedeutung ist vom Kommando abhängig)
+ ///
+ COUNTER_REACHED = 0x63C0,
+
+ ///
+ /// Warnung; Zustand des nichtflüchtigen Speichers verändert
+ ///
+ STORAGE_CHANGED = 0x6300,
+
+ ///
+ /// Ausführungsfehler; Zustand des nichtflüchtigen Speichers nicht verändert
+ ///
+ EXECUTION_ERROR_WITHOUT_CHANGE = 0x6400,
+
+ ///
+ /// Speicherfehler
+ ///
+ MEMORY_ERROR = 0x6581,
+
+ ///
+ /// Ausführungsfehler; Zustand des nichtflüchtigen Speichers verändert
+ ///
+ EXECUTION_ERROR_WITH_CHANGE = 0x6500,
+
+ ///
+ /// Befehlslänge (Lc) oder erwartete Antwortlänge (Le) falsch
+ ///
+ INVALID_LC_LE = 0x6700,
+
+ ///
+ /// Funktionen im Class-Byte werden nicht unterstützt
+ ///
+ CLASS_FEATURE_NOT_SUPPORTED = 0x6800,
+
+ ///
+ /// Logische Kanäle werden nicht unterstützt
+ ///
+ LOGIC_CHANNEL_NOT_SUPPORTED = 0x6881,
+
+ ///
+ /// Secure Messaging wird nicht unterstützt
+ ///
+ SECURE_MESSAGING_NOT_SUPPORTED = 0x6882,
+
+ ///
+ /// Kommando nicht erlaubt
+ ///
+ COMMAND_NOT_ALLOWED = 0x6900,
+
+ ///
+ /// Kommando inkompatibel zur Dateistruktur
+ ///
+ COMMAND_INCOMPATIBLE = 0x6981,
+
+ ///
+ /// Sicherheitszustand nicht erfüllt
+ ///
+ SAFETY_STATUS_NOT_FULFILLED = 0x6982,
+
+ ///
+ /// Authentisierungsmethode ist gesperrt
+ ///
+ AUTHENTICATION_METHOD_LOCKED = 0x6983,
+
+ ///
+ /// Referenzierte Daten sind gesperrt
+ ///
+ REFERENCED_FILE_LOCKED = 0x6984,
+
+ ///
+ /// Nutzungsbedingungen sind nicht erfüllt
+ ///
+ TERMS_OF_SERVICE_NOT_FULFILLED = 0x6985,
+
+ ///
+ /// Kommando nicht erlaubt (kein EF selektiert)
+ ///
+ COMMAND_NOT_ALLOWED_NO_EF_SELECTED = 0x6986,
+
+ ///
+ /// Erwartete Secure-Messaging-Objekte nicht gefunden
+ ///
+ EXPECTED_SECURE_MESSAGING_OBJECTS_NOT_FOUND = 0x6987,
+
+ ///
+ /// Secure-Messaging-Datenobjekte sind inkorrekt
+ ///
+ INVALID_SECURE_MESSAGING_OBJECTS = 0x6988,
+
+ ///
+ /// Falsche Parameter P1/P2
+ ///
+ WRONG_PARAMETERS = 0x6A00,
+
+ ///
+ /// Falsche Daten
+ ///
+ WRONG_DATA = 0x6A80,
+
+ ///
+ /// Funktion wird nicht unterstützt
+ ///
+ FEATURE_NOT_SUPPORTED = 0x6A81,
+
+ ///
+ /// Datei wurde nicht gefunden
+ ///
+ FILE_NOT_FOUND = 0x6A82,
+
+ ///
+ /// Datensatz (engl. record) der Datei nicht gefunden
+ ///
+ RECORD_NOT_FOUND = 0x6A83,
+
+ ///
+ /// Nicht genügend Speicherplatz in der Datei
+ ///
+ INSUFFICIENT_SPACE = 0x6A84,
+
+ ///
+ /// Lc nicht konsistent mit der TLV-Struktur
+ ///
+ LC_TLV_INCONSISTENT = 0x6A85,
+
+ ///
+ /// Inkorrekte Parameter P1/P2
+ ///
+ INCORRECT_PARAMETERs = 0x6A86,
+
+ ///
+ /// Lc inkonsistent mit P1/P2
+ ///
+ LC_PARAMETERS_INCONSISTENT = 0x6A87,
+
+ ///
+ /// Referenzierte Daten nicht gefunden
+ ///
+ REFERENCED_FILE_NOT_FOUND = 0x6A88,
+
+ ///
+ /// Parameter P1/P2 falsch
+ ///
+ WRONG_PARAMETERS_2 = 0x6B00,
+
+ ///
+ /// Falsche Länge Le; xx gibt die korrekte Länge an Statuswort zur Steuerung des T=0-Protokolls
+ ///
+ INVALID_LE = 0x6C00,
+
+ ///
+ /// Das Kommando (INS) wird nicht unterstützt
+ ///
+ INSTRUCTION_NOT_SUPPORTED = 0x6D00,
+
+ ///
+ /// Die Kommandoklasse (CLA) wird nicht unterstützt
+ ///
+ CLASS_NOT_SUPPORTED = 0x6E00,
+
+ ///
+ /// Kommando wurde mit unbekanntem Fehler abgebrochen
+ ///
+ UNKNOWN_ERROR = 0x6F00,
+
+ ///
+ /// Kommando erfolgreich ausgeführt
+ ///
+ SUCCESS = 0x9000,
+ }
+}
diff --git a/NFC/IReader.cs b/NFC/IReader.cs
index a0b05b1..d068f9e 100644
--- a/NFC/IReader.cs
+++ b/NFC/IReader.cs
@@ -1,6 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Text;
namespace NFC
{
@@ -16,16 +14,18 @@ namespace NFC
bool IsAvailable();
/// Returns all available readers.
- String[] GetReader();
+ string[] GetReaders();
///
/// Create a new reader instance from the specified id.
///
/// Returns the spatform specific reader that corresponds to the id.
/// Invalid reader id.
- IReader OpenReader(String readerID);
+ IReader OpenReader(string readerID);
}
+ public delegate void ReaderEventHandler(object sender, ICard card);
+
///
/// Abstraction of a platform-specifc reader that can communicate with NFC cards.
///
@@ -34,12 +34,12 @@ namespace NFC
///
/// Event that will be called when a new tag was discovered.
///
- event EventHandler CardDiscovered;
+ event ReaderEventHandler CardDiscovered;
///
/// Event that will be called when a tag that is in use gets disconnected.
///
- event EventHandler CardLost;
+ event ReaderEventHandler CardLost;
void start();
@@ -63,7 +63,7 @@ namespace NFC
///
/// Application Protocol Data Unit Command - ISO 7816
/// Application Protocol Data Unit Response - ISO 7816
- byte[] Transmit(byte[] apdu_cmd);
+ APDUResponse Transmit(APDUCommand apdu_cmd);
}
public class ReaderUnavailableException : Exception { }
diff --git a/NFC/Mifare DESFire/APDUInstructions.cs b/NFC/Mifare DESFire/APDUInstructions.cs
new file mode 100644
index 0000000..dd3025c
--- /dev/null
+++ b/NFC/Mifare DESFire/APDUInstructions.cs
@@ -0,0 +1,44 @@
+namespace NFC.Mifare_DESFire
+{
+ enum APDUInstructions : byte
+ {
+ AUTHENTICATE_ISO = 0x1A,
+ AUTHENTICATE_AES = 0xAA,
+ CHANGE_KEY_SETTINGS = 0x54,
+ SET_CONFIGURATION = 0x5C,
+ CHANGE_KEY = 0xC4,
+ GET_KEY_VERSION = 0x64,
+ CREATE_APPLICATION = 0xCA,
+ DELETE_APPLICATION = 0xDA,
+ GET_APPLICATION_IDS = 0x6A,
+ FREE_MEMORY = 0x6E,
+ GET_DF_NAMES = 0x6D,
+ GET_KEY_SETTINGS = 0x45,
+ SELECT_APPLICATION = 0x5A,
+ FORMAT_PICC = 0xFC,
+ GET_VERSION = 0x60,
+ GET_CARD_UID = 0x51,
+ GET_FILE_IDS = 0x6F,
+ GET_FILE_SETTINGS = 0xF5,
+ CHANGE_FILE_SETTINGS = 0x5F,
+ CREATE_STDDATAFILE = 0xCD,
+ CREATE_BACKUPDATAFILE = 0xCB,
+ CREATE_VALUE_FILE = 0xCC,
+ CREATE_LINEAR_RECORD_FILE = 0xC1,
+ CREATE_CYCLIC_RECORD_FILE = 0xC0,
+ DELETE_FILE = 0xDF,
+ GET_ISO_FILE_IDS = 0x61,
+ READ_DATA = 0x8D,
+ WRITE_DATA = 0x3D,
+ GET_VALUE = 0x6C,
+ CREDIT = 0x0C,
+ DEBIT = 0xDC,
+ LIMITED_CREDIT = 0x1C,
+ WRITE_RECORD = 0x3B,
+ READ_RECORDS = 0xBB,
+ CLEAR_RECORD_FILE = 0xEB,
+ COMMIT_TRANSACTION = 0xC7,
+ ABORT_TRANSACTION = 0xA7,
+ CONTINUE = 0xAF,
+ }
+}
diff --git a/NFC/Mifare DESFire/APDUStatusCodes.cs b/NFC/Mifare DESFire/APDUStatusCodes.cs
new file mode 100644
index 0000000..a06327b
--- /dev/null
+++ b/NFC/Mifare DESFire/APDUStatusCodes.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NFC.Mifare_DESFire
+{
+ public enum APDUStatusCodes : UInt16
+ {
+ OPERATION_OK = 0x9000, // = Successful operation
+ NO_CHANGES = 0x900C, // = No changes done to backup files, CommitTransaction / AbortTransaction not necessary
+ OUT_OF_EEPROM_ERROR = 0x900E, // = Insufficient NV-Memory to complete command
+ ILLEGAL_COMMAND_CODE = 0x901C, // = Command code not supported
+ INTEGRITY_ERROR = 0x901E, // = CRC or MAC does not match data Padding bytes not valid
+ NO_SUCH_KEY = 0x9040, // = Invalid key number specified
+ LENGTH_ERROR = 0x907E, // = Length of command string invalid
+ PERMISSION_DENIED = 0x909D, // = Current configuration / status does not allow the requested command
+ PARAMETER_ERROR = 0x909E, // = Value of the parameter(s) invalid
+ APPLICATION_NOT_FOUND = 0x90A0, // = Requested AID not present on PICC
+ APPL_INTEGRITY_ERROR = 0x90A1, // = Unrecoverable error within application, application will be disabled
+ AUTHENTICATION_ERROR = 0x90AE, // = Current authentication status does not allow the requested command
+ ADDITIONAL_FRAME = 0x90AF, // = Additional data frame is expected to be sent
+ BOUNDARY_ERROR = 0x90BE, // = Attempt to read/write data from/to beyond the file\'s/record\'s limits. Attempt to exceed the limits of a value file.
+ PICC_INTEGRITY_ERROR = 0x90C1, // = Unrecoverable error within PICC, PICC will be disabled
+ COMMAND_ABORTED = 0x90CA, // = Previous Command was not fully completed Not all Frames were requested or provided by the PCD
+ PICC_DISABLED_ERROR = 0x90CD, // = PICC was disabled by an unrecoverable error
+ COUNT_ERROR = 0x90CE, // = Number of Applications limited to 28, no additional CreateApplication possible
+ DUPLICATE_ERROR = 0x90DE, // = Creation of file/application failed because file/application with same number already exists
+ EEPROM_ERROR = 0x90EE, // = Could not complete NV-write operation due to loss of power, internal backup/rollback mechanism activated
+ FILE_NOT_FOUND = 0x90F0, // = Specified file number does not exist
+ FILE_INTEGRITY_ERROR = 0x90F1, // = Unrecoverable error within file, file will be disabled
+ }
+}
\ No newline at end of file
diff --git a/NFC/Mifare DESFire/CryptoOperations.cs b/NFC/Mifare DESFire/CryptoOperations.cs
new file mode 100644
index 0000000..0ae77af
--- /dev/null
+++ b/NFC/Mifare DESFire/CryptoOperations.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NFC.Mifare_DESFire
+{
+ enum CryptoOperations : byte
+ {
+ TDES = 0x00,
+ TKTDES = 0x40,
+ AES = 0x80,
+ }
+}
diff --git a/NFC/Mifare DESFire/FileCommunication.cs b/NFC/Mifare DESFire/FileCommunication.cs
new file mode 100644
index 0000000..efce035
--- /dev/null
+++ b/NFC/Mifare DESFire/FileCommunication.cs
@@ -0,0 +1,20 @@
+namespace NFC.Mifare_DESFire
+{
+ enum FileCommunication : byte
+ {
+ ///
+ /// "Plain communication"
+ ///
+ PLAIN = 0x00,
+
+ ///
+ /// Plain communication secured by DES/3DES MACing
+ ///
+ MAC = 0x01,
+
+ ///
+ /// Fully DES/3DES enciphered communication
+ ///
+ ENCRYPT = 0x03
+ }
+}
diff --git a/NFC/Mifare DESFire/FileTypes.cs b/NFC/Mifare DESFire/FileTypes.cs
new file mode 100644
index 0000000..9c1fb13
--- /dev/null
+++ b/NFC/Mifare DESFire/FileTypes.cs
@@ -0,0 +1,30 @@
+namespace NFC.Mifare_DESFire
+{
+ enum FileTypes : byte
+ {
+ ///
+ /// Standard Data File
+ ///
+ STANDARD = 0x00,
+
+ ///
+ /// Backup Data Files
+ ///
+ BACKUP = 0x01,
+
+ ///
+ /// Value Files with Backup
+ ///
+ VALUE = 0x02,
+
+ ///
+ /// Linear Record Files with Backup
+ ///
+ LINEARRECORD = 0x03,
+
+ ///
+ /// Cyclic Record Files with Backup
+ ///
+ CYCLICRECORD = 0x04
+ }
+}
diff --git a/NFC/NFC.csproj b/NFC/NFC.csproj
index cb63190..3c87e5e 100644
--- a/NFC/NFC.csproj
+++ b/NFC/NFC.csproj
@@ -4,4 +4,9 @@
netcoreapp3.1
+
+
+
+
+
diff --git a/NFC/Readers/PCSC/Card.cs b/NFC/Readers/PCSC/Card.cs
new file mode 100644
index 0000000..cd70e1b
--- /dev/null
+++ b/NFC/Readers/PCSC/Card.cs
@@ -0,0 +1,63 @@
+using PCSC;
+using PCSC.Iso7816;
+
+namespace NFC.Readers.PCSC
+{
+ public class Card : ICard
+ {
+ private IsoReader _ISOReader;
+ private string _ReaderID;
+
+ public Card(IsoReader isoreader, string readerID)
+ {
+ _ISOReader = isoreader;
+ _ReaderID = readerID;
+ }
+ public void Connect()
+ {
+ _ISOReader.Connect(_ReaderID, SCardShareMode.Shared, SCardProtocol.Any);
+ }
+
+ public void Disconnect()
+ {
+ _ISOReader.Disconnect(SCardReaderDisposition.Eject);
+ }
+
+ public APDUResponse Transmit(APDUCommand apdu_cmd)
+ {
+ Response response = _ISOReader.Transmit(Convert(apdu_cmd));
+ return Convert(response);
+ }
+
+ public CommandApdu Convert(APDUCommand apdu_cmd)
+ {
+ CommandApdu apdu = new CommandApdu(IsoCase.Case2Short, _ISOReader.ActiveProtocol)
+ {
+ CLA = apdu_cmd.Class,
+ INS = apdu_cmd.Instruction,
+ P1 = apdu_cmd.Parameter1,
+ P2 = apdu_cmd.Parameter2,
+
+ Data = apdu_cmd.Data,
+
+ Le = apdu_cmd.LengthExpected
+ };
+
+ return apdu;
+ }
+
+ public APDUResponse Convert(Response response)
+ {
+ ResponseApdu responseApdu = response.Get(0);
+
+ APDUResponse apduResponse = new APDUResponse()
+ {
+ SW1 = responseApdu.SW1,
+ SW2 = responseApdu.SW2,
+ Body = responseApdu.GetData()
+ };
+
+ return apduResponse;
+ }
+ }
+}
diff --git a/NFC/Readers/PCSC/Hardware.cs b/NFC/Readers/PCSC/Hardware.cs
new file mode 100644
index 0000000..efc2373
--- /dev/null
+++ b/NFC/Readers/PCSC/Hardware.cs
@@ -0,0 +1,33 @@
+using PCSC;
+
+namespace NFC.Readers.PCSC
+{
+ public class Hardware : IHardware
+ {
+ public string[] GetReaders()
+ {
+ var contextFactory = ContextFactory.Instance;
+ using (var context = contextFactory.Establish(SCardScope.System))
+ {
+ return context.GetReaders();
+ }
+ }
+
+ public bool IsAvailable()
+ {
+ if(GetReaders().Length == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ public IReader OpenReader(string readerID)
+ {
+ return new Reader(readerID);
+ }
+ }
+}
diff --git a/NFC/Readers/PCSC/Reader.cs b/NFC/Readers/PCSC/Reader.cs
new file mode 100644
index 0000000..d3e9686
--- /dev/null
+++ b/NFC/Readers/PCSC/Reader.cs
@@ -0,0 +1,51 @@
+using PCSC;
+using PCSC.Iso7816;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NFC.Readers.PCSC
+{
+
+ public class Reader : IReader, IDisposable
+ {
+ private string _ReaderID;
+ private IContextFactory _ContextFactory;
+ private ISCardContext _SCardContext;
+ private IsoReader _ISOReader;
+ private ICard _Card;
+
+ public Reader(string readerID)
+ {
+ _ReaderID = readerID;
+ }
+
+ public event ReaderEventHandler CardDiscovered;
+ public event ReaderEventHandler CardLost;
+
+ public void Dispose()
+ {
+ stop();
+ }
+
+ public void start()
+ {
+ _ContextFactory = ContextFactory.Instance;
+ _SCardContext = _ContextFactory.Establish(SCardScope.System);
+
+ _ISOReader = new IsoReader(_SCardContext);
+
+ _Card = new Card(_ISOReader, _ReaderID);
+
+ CardDiscovered?.Invoke(this, _Card);
+ }
+
+ public void stop()
+ {
+ CardLost?.Invoke(this, _Card);
+
+ _ISOReader.Dispose();
+ _SCardContext.Dispose();
+ }
+ }
+}
diff --git a/NFC_Test/NFC_Test.csproj b/NFC_Test/NFC_Test.csproj
new file mode 100644
index 0000000..df2e516
--- /dev/null
+++ b/NFC_Test/NFC_Test.csproj
@@ -0,0 +1,17 @@
+
+
+
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs
new file mode 100644
index 0000000..f144ee8
--- /dev/null
+++ b/NFC_Test/REAL_Windows.cs
@@ -0,0 +1,37 @@
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NFC;
+using NFC.Readers.PCSC;
+
+namespace NFC_Test
+{
+ [TestFixture, Explicit]
+ public class REAL_Windows
+ {
+ [Test]
+ public void GetReaders()
+ {
+ Hardware hardware = new Hardware();
+ string[] readers = hardware.GetReaders();
+
+ Console.WriteLine("Readers detected: {0}", readers.Length);
+
+ if(readers.Length > 0)
+ {
+ Console.WriteLine("List of ReaderIDs:");
+ foreach (string readerID in readers)
+ {
+ Console.WriteLine("{0}", readerID);
+ }
+ }
+ }
+
+ [TestCase("")]
+ public void Connect(string readerID)
+ {
+
+ }
+ }
+}