private void HandleMifareUL(ICardReader reader)
        {
            var mifare = new PcscSdk.MifareUltralight.AccessHandler(reader);

            StatusMessage?.Invoke("Handling as Mifare Ultralight");

            byte[] uid = mifare.GetUid();
            StatusMessage?.Invoke("UID: " + BitConverter.ToString(uid));
            Array.Resize(ref uid, uid.Length + 1);
            uid[uid.Length - 1] = 0xAA;
            NewTagUid?.Invoke(uid);

            byte[] infoData = mifare.Read(0);
            StatusMessage?.Invoke("CC: " + BitConverter.ToString(infoData.Skip(12).ToArray()));

            try
            {
                byte[] versionData = mifare.GetVersion();
                StatusMessage?.Invoke("Mifare Version: " + BitConverter.ToString(versionData));

                int capacity    = versionData[6] >> 1;
                int capacityMax = capacity;
                if ((versionData[6] & 1) == 1)
                {
                    capacityMax += 1;
                }
                capacity    = (int)Math.Pow(2, capacity);
                capacityMax = (int)Math.Pow(2, capacityMax);
                StatusMessage?.Invoke("Capacity is between " + capacity + " and " + capacityMax + " bytes");
            }
            catch (ApduFailedException e)
            {
                StatusMessage?.Invoke("Failed getting Mifare Version: " + e.Message);
            }

            byte identMagic    = infoData[12];
            byte identVersion  = infoData[13];
            int  identCapacity = infoData[14] * 8;
            int  major         = identVersion >> 4;
            int  minor         = identVersion & 0x0F;

            if (identMagic != 0xE1 || identVersion < 0x10)
            {
                throw new NfcHandlerException("Tag format is unsupported");
            }

            StatusMessage?.Invoke("Found Type 2 Tag version " + major + "." + minor + " with " + identCapacity + " bytes capacity.");

            if (ndefDataToWrite != null)
            {
                WriteNdefToMifareUL(mifare, ndefDataToWrite);
                ndefDataToWrite = null;
            }
            else
            {
                byte[] data = DumpMifareUL(mifare);
                ParseTLVData(data);
            }
        }
        private byte[] DumpMifareUL(PcscSdk.MifareUltralight.AccessHandler mifare)
        {
            byte[] infoData   = mifare.Read(3);
            int    bytes_left = infoData[2] * 8;

            byte[] res = new byte[bytes_left];

            for (byte pos = 4; bytes_left > 0; pos += 4, bytes_left -= 16)
            {
                byte[] data = mifare.Read(pos);
                if (bytes_left < 16)
                {
                    data = data.Take(bytes_left).ToArray();
                }

                data.CopyTo(res, (pos - 4) * 4);
            }

            return(res);
        }
        private void WriteNdefToMifareUL(PcscSdk.MifareUltralight.AccessHandler mifare, byte[] ndefData)
        {
            byte[] infoData = mifare.Read(3);
            int    capacity = infoData[2] * 8;

            byte[] wrappedData = GenerateTLVData(ndefData);

            if (wrappedData.Length > capacity)
            {
                throw new NfcHandlerException("Data size of " + wrappedData.Length + " bytes exceeds capacity of " + capacity + " bytes!");
            }

            int data_length = wrappedData.Length;

            Array.Resize(ref wrappedData, (data_length / 4) * 4 + 4);

            for (byte pos = 4; (pos - 4) * 4 < wrappedData.Length; pos++)
            {
                mifare.Write(pos, wrappedData.Skip((pos - 4) * 4).Take(4).ToArray());
            }

            StatusMessage?.Invoke("Written " + data_length + " bytes of data. Ndef message length is " + ndefData.Length + " bytes.");
        }