using System.CommandLine; using PCSC; using PCSC.Monitoring; using PCSC.Iso7816; var rootCommand = new RootCommand("Fancy Test Machine for AfRApay"); var listReadersOption = new Option("--list-readers", "List card readers and exit"); rootCommand.Add(listReadersOption); rootCommand.SetHandler((listReaders) => { using (var context = ContextFactory.Instance.Establish(SCardScope.System)) { // We need a card reader or this won't work! var readerNames = context.GetReaders(); if (readerNames.Length == 0) { Console.Error.WriteLine("Error: no card reader detected"); Environment.Exit(1); } // If --list-readers is passed, list readers and exit. if (listReaders) { Console.Error.WriteLine("---------- Connected Readers ----------"); foreach (var name in readerNames) { Console.WriteLine(name); } Console.Error.WriteLine("---------------------------------------"); Environment.Exit(0); } // Listen for events on all connected readers. using (var monitor = MonitorFactory.Instance.Create(SCardScope.System)) { monitor.Initialized += (_, args) => Console.WriteLine("[ Reader Initialized: {0} ]", args.ReaderName); monitor.MonitorException += (_, args) => { Console.Error.WriteLine("! ERROR: {0}", args); Environment.Exit(1); }; monitor.StatusChanged += (_, args) => Console.WriteLine("~ {0} -> {1}", args.LastState, args.NewState); monitor.CardInserted += (_, args) => { Console.WriteLine("> TAP: {0}", Convert.ToHexString(args.Atr)); var reader = new IsoReader(context, args.ReaderName, SCardShareMode.Shared, SCardProtocol.Any); HandleTap(reader); }; monitor.CardRemoved += (_, args) => { Console.WriteLine("< OFF"); Console.WriteLine(); // Write a blank line between card taps for readability. }; Console.WriteLine("[ Starting... ]"); monitor.Start(readerNames); while (true) { Console.Read(); } } } }, listReadersOption); return await rootCommand.InvokeAsync(args); // Queries a card for data when one is tapped. static void HandleTap(IsoReader reader) { // Send a PCSC pseudo-APDU to query the ISO 14443 UID. var rsp = reader.Transmit(new CommandApdu(IsoCase.Case2Short, SCardProtocol.Any) { CLA = 0xFF, Instruction = InstructionCode.GetData, P1 = 0x00, P2 = 0x00, }); if (!IsSucc(rsp)) { Console.Error.WriteLine("--> Card Error: SW1={0} SW2={1}", (SW1Code)rsp.SW1, rsp.SW2); return; } var uid = rsp.GetData(); Console.WriteLine(" UID: {0}", Convert.ToHexString(uid)); } // Was the command successful? static bool IsSucc(Response rsp) { return rsp.SW1 == (byte)SW1Code.Normal && rsp.SW2 == 0x00; }