using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Linq;
using System.Management;
using System.Diagnostics;

namespace cn.mineki.Reader
{
    
    public enum ReaderPortNum
    {
        SDT_COM1 = 1, SDT_COM2, SDT_COM3, SDT_COM4, SDT_COM5, SDT_COM6, SDT_COM7, SDT_COM8, SDT_COM9, SDT_COM10, SDT_COM11, SDT_COM12, SDT_COM13, SDT_COM14, SDT_COM15, SDT_COM16,
        SDT_USB1 = 1001, SDT_USB2, SDT_USB3, SDT_USB4, SDT_USB5, SDT_USB6, SDT_USB7, SDT_USB8, SDT_USB9, SDT_USB10, SDT_USB11, SDT_USB12, SDT_USB13, SDT_USB14, SDT_USB15, SDT_USB16,
        HID = 2401,RF200_COM1 = 2501, RF200_COM2, RF200_COM3, RF200_COM4, RF200_COM5, RF200_COM6
    };

    public enum ReaderSlotNum
    {
        TypeA=1, TypeB,ISO15693,DN,Mifare1,SmartCard,PsamCard,RFDCard=0x11
    };
    
    public class IDCardReader
    {
        static bool is64bit = (IntPtr.Size == 8);
        #region 民族表
        static public string[] Nation = {"无",	
		"汉族","蒙古族","回族","藏族","维吾尔族",
        "苗族","彝族","壮族","布依族","朝鲜族",
        "满族",
        "侗族",
        "瑶族",
        "白族",
        "土家族",
        "哈尼族",
        "哈萨克族",
        "傣族",
        "黎族",
        "傈僳族",
        "佤族",
        "畲族",
        "高山族",
        "拉祜族",
        "水族",
        "东乡族",
        "纳西族",
        "景颇族",
        "柯尔克孜族",
        "土族",
        "达斡尔族",
        "仫佬族",
        "羌族",
        "布朗族",
        "撒拉族",
        "毛难族",
        "仡佬族",
        "锡伯族",
        "阿昌族",
        "普米族",
        "塔吉克族",
        "怒族",
        "乌孜别克",
        "俄罗斯族",
        "鄂温克族",
        "崩龙族",
        "保安族",
        "裕固族",
        "京族",
        "塔塔尔族",
        "独龙族",
        "鄂伦春族",
        "赫哲族",
        "门巴族",
        "珞巴族",
        "其它",
        "外国血统"};
        #endregion

        #region 导入函数        
        public static int Buzzer(byte beepTime, byte waitTime, byte beepCount)
        {
            return is64bit ? MKReader64.Buzzer64(beepTime,waitTime,beepCount) : MKReader32.Buzzer32(beepTime, waitTime, beepCount);
        }

        public static int InitComm(ReaderPortNum port)
        { return is64bit ? MKReader64.InitComm64(port) : MKReader32.InitComm32(port);  }

        public static int CloseComm()
        { return is64bit ? MKReader64.CloseComm64() : MKReader32.CloseComm32(); }

        public static int Authenticate()
        { return is64bit ? MKReader64.Authenticate64() : MKReader32.Authenticate32(); }

        public static int Read_Content(int active)
        {
            return (is64bit ? MKReader64.Read_Content64(active) : MKReader32.Read_Content32(active));            
        }

        public static int Read_Content_Path(string path, int active)
        { return is64bit ? MKReader64.Read_Content64(active) : MKReader32.Read_Content32(active); }

        public static int GetSAMID([MarshalAs(UnmanagedType.LPArray)]byte[] id)
        { return is64bit ? MKReader64.GetSAMID64(id) : MKReader32.GetSAMID32(id); }

        public static int TransApduCommand(ReaderSlotNum nReaderSlot, [MarshalAs(UnmanagedType.LPArray)]byte[] pSendDatas, int nSendLen, [MarshalAs(UnmanagedType.LPArray)]byte[] pRecvDatas, ref int nRecvLen)
        { return is64bit ? MKReader64.TransApduCommand64(nReaderSlot, pSendDatas, nSendLen, pRecvDatas, ref nRecvLen) : MKReader32.TransApduCommand32(nReaderSlot, pSendDatas, nSendLen, pRecvDatas, ref nRecvLen); }

        public static int ActivateCard(ReaderSlotNum nReaderSlot, [MarshalAs(UnmanagedType.LPArray)]byte[] pRecvDatas, ref int nRecvLen)
        { return is64bit ? MKReader64.ActivateCard64(nReaderSlot,  pRecvDatas, ref nRecvLen) : MKReader32.ActivateCard32(nReaderSlot, pRecvDatas, ref nRecvLen); }

        public static int SetAntPower(int nPowerOn)
        { return is64bit ? MKReader64.SetAntPower64(nPowerOn) : MKReader32.SetAntPower32(nPowerOn); }

        #region ISO7816
        public static int ISO7816_CardInsert(ReaderSlotNum nSlot)
        { return is64bit ? MKReader64.ISO7816_CardInsert64(nSlot) : MKReader32.ISO7816_CardInsert32(nSlot); }
        public static int ISO7816_CardRemove(ReaderSlotNum nSlot)
        { return is64bit ? MKReader64.ISO7816_CardRemove64(nSlot) : MKReader32.ISO7816_CardRemove32(nSlot); }
        public static int ISO7816_TransApdu(ReaderSlotNum nReaderSlot, [MarshalAs(UnmanagedType.LPArray)]byte[] pSendDatas, int nSendLen, [MarshalAs(UnmanagedType.LPArray)]byte[] pRecvDatas,ref int nRecvLen)
        { return is64bit ? MKReader64.ISO7816_TransApdu64(nReaderSlot, pSendDatas, nSendLen, pRecvDatas, ref nRecvLen) : MKReader32.ISO7816_TransApdu32(nReaderSlot, pSendDatas, nSendLen, pRecvDatas, ref nRecvLen); }
        #endregion

        public static int ISO14443_TransApdu(ReaderSlotNum nReaderSlot, [MarshalAs(UnmanagedType.LPArray)]byte[] pSendDatas, int nSendLen, [MarshalAs(UnmanagedType.LPArray)]byte[] pRecvDatas, ref int nRecvLen)
        { return is64bit ? MKReader64.ISO14443_TransApdu64(nReaderSlot, pSendDatas, nSendLen, pRecvDatas, ref nRecvLen) : MKReader32.ISO14443_TransApdu32(nReaderSlot, pSendDatas, nSendLen, pRecvDatas, ref nRecvLen); }

        #region 机读旅行证件相关函数
        //---------------------------------------------------------------------------
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct EPP_Info
        {
            [MarshalAs(UnmanagedType.U4)]
            public uint DocumentType; //证件类型 10014--NewGAHXZ; 19014--OldGAHXZ; 10025--NewTBZ
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
            public string DocumentNumber;        //TXZ号码	
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 62)]
            public string Name;          //英文姓名
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
            public string Gender;            //性别
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
            public string DateOfBorn;     //生日YYMMDD
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
            public string DateOfExpiry; //证件有效期至YYMMDD
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
            public string DateOfIssue;     //签发日期YYMMDD

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
            public string IssuingCountryIso;   //签发国代码XXX
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 62)]
            public string IssuingCountryName;   //签发国名称
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
            public string NationalityIso;   //国籍或民族代码
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 62)]
            public string NationalityName;//国籍或民族名称

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
            public string IssuedTimes;      //换证次数XX
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
            public string CustNo;      //港澳回乡证上的港澳证件号码//新版港澳回乡证上的港澳证件号码或新版台胞证上的身份证号码
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string CustName;     //中文姓名
            
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 76)]
            public string AddressOfBorn;  //出生地点
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 76)]
            public string Address;      //住址	
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 98)]
            public string MRZ;   //芯片机读码，非必需字段
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 46)]
            public string MRZ1;   //芯片机读码，非必需字段
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 46)]
            public string MRZ2;   //芯片机读码，非必需字段
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 46)]
            public string MRZ3;   //芯片机读码，非必需字段
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
            public string PhotoName;
        }

        //---------------------------------------------------------------------------
        public static int EPP_GetInfo(ref EPP_Info pInfo)
        { return is64bit ? MKReader64.EPP_GetInfo64(ref pInfo) : MKReader32.EPP_GetInfo32(ref pInfo); }

        public static int EPP_Authentication(string pn, string bod, string eod)
        { return is64bit ? MKReader64.EPP_Authentication64(pn, bod, eod) : MKReader32.EPP_Authentication32(pn, bod, eod); }

        public static int EPP_Read_Content(int active)
        { return is64bit ? MKReader64.EPP_Read_Content64(active) : MKReader32.EPP_Read_Content32(active); }

        public static int EPP_Read_Content_Path(string cPath, int active)
        { return is64bit ? MKReader64.EPP_Read_Content_Path64(cPath, active) : MKReader32.EPP_Read_Content_Path32(cPath, active); }

        public static string EPP_Parse_DocumentType(uint type)
        {
            //护照(P)
            if (type == 0) return "护照";
            else if (type == 1) return "旧版回乡证";
            else if (type == 2) return "新版回乡证";
            else if (type == 3) return "旧版台胞证";
            else if (type == 4) return "新版台胞证";
            else if (type == 5) return "旧版港澳通行证";
            else if (type == 6) return "新版港澳通行证";
            else if (type == 7) return "旧版台湾通行证";
            else if (type == 8) return "新版台湾通行证";
            else if (type == 9) return "MRTD标准身份证";
            else if (type == 10) return "绿卡";
            else if (type == 11) return "MRTD标准TD1证件";
            else if (type == 12) return "MRTD标准TD2证件";
            else if (type == 13) return "MRTD标准TD3证件";
            else if (type == 14) return "新版港澳通行证OCR";
            else if (type == 15) return "新版台湾通行证OCR";
            else if (type == 16) return "旧版中国护照";
            else if (type == 17) return "新版中国护照";
            else if (type == 18) return "护照签注";
            else if (type == 19) return "旧版港澳通行证签注";
            else if (type == 20) return "旧版台湾通行证签注";
            else if (type == 21) return "旧版台胞证签注";
            return "未知证件";
        }
        #endregion

        #region 读取银行卡
        //---------------------------------------------------------------------------
        [StructLayout(LayoutKind.Sequential)]
        public struct BC_INFO
        {
            [MarshalAs(UnmanagedType.U4)]
            public uint DG0201_Len;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)]
            public byte[] DG0201;

            [MarshalAs(UnmanagedType.U4)]
            public uint DG0101_Len;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)]
            public byte[] DG0101;

            [MarshalAs(UnmanagedType.U4)]
            public uint DG0102_Len;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)]
            public byte[] DG0102;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
            public byte[] ICCardNo;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
            public byte[] IDNo;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
            public byte[] Name;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
            public byte[] ValidThru;

            [MarshalAs(UnmanagedType.U4)]
            public uint Track1Len;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 200)]
            public byte[] Track1;
            [MarshalAs(UnmanagedType.U4)]
            public uint Track2Len;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 200)]
            public byte[] Track2;
        };
        public static int BC_Read_Content(ref BC_INFO info)
        { return is64bit ? MKReader64.BC_Read_Content64(ref info) : MKReader32.BC_Read_Content32(ref info); }
        #endregion

        #region 读取社保卡
        //---------------------------------------------------------------------------
        [StructLayout(LayoutKind.Sequential)]
        public struct SSC_INFO
        {
            [MarshalAs(UnmanagedType.U4)]
            public uint SSSE_EF05_Len;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
            public byte[] SSSE_EF05;

            [MarshalAs(UnmanagedType.U4)]
            public uint SSSE_EF06_Len;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
            public byte[] SSSE_EF06;

            [MarshalAs(UnmanagedType.U4)]
            public uint SSSE_EF07_Len;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 300)]
            public byte[] SSSE_EF07;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
            public byte[] ICCardNo;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
            public byte[] IDNo;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
            public byte[] Name;
        };

        public static int SSC_Authentication(ReaderSlotNum nReaderSlot)
        { return is64bit? MKReader64.SSC_Authentication64(nReaderSlot) : MKReader32.SSC_Authentication32(nReaderSlot); }

        public static int SSC_Read_Content(ReaderSlotNum nReaderSlot, ref SSC_INFO info)
        { return is64bit ? MKReader64.SSC_Read_Content64(nReaderSlot, ref info) : MKReader32.SSC_Read_Content32(nReaderSlot, ref info); }
        #endregion

        #region 读取电子身份证
        //---------------------------------------------------------------------------
        public static int EID_Authentication(byte[] byEidCardID)
        { return is64bit ? MKReader64.EID_Authentication64(byEidCardID) : MKReader32.EID_Authentication32(byEidCardID); }

        public static int EID_Read_Content(byte[] byEidCardID)
        { return is64bit ? MKReader64.EID_Read_Content64(byEidCardID) : MKReader32.EID_Read_Content32(byEidCardID); }
        #endregion

        #region  ISO15693标签
        public static int ISO15693_ReadSingleBlock(bool readSecSta, int nBlkAddr, byte[] bufBlockDat, int nSize, ref int bytesBlkDatRead)
        { return is64bit ? MKReader64.ISO15693_ReadSingleBlock64(readSecSta, nBlkAddr, bufBlockDat, nSize,ref bytesBlkDatRead) : MKReader32.ISO15693_ReadSingleBlock32(readSecSta, nBlkAddr, bufBlockDat, nSize, ref bytesBlkDatRead); }

        public static int ISO15693_WriteSingleBlock(int blkAddr, byte[] newBlkData, int bytesToWrite)
        { return is64bit ? MKReader64.ISO15693_WriteSingleBlock64(blkAddr, newBlkData, bytesToWrite) : MKReader32.ISO15693_WriteSingleBlock32(blkAddr, newBlkData, bytesToWrite); }

        public static int ISO15693_ReadMultiBlocks(bool readSecSta, int nBlkAddr, int numOfBlksToRead, ref int numOfBlksRead, byte[] bufBlockDat, int nSize, ref int bytesBlkDatRead)
        { return is64bit ? MKReader64.ISO15693_ReadMultiBlocks64(readSecSta, nBlkAddr, numOfBlksToRead, ref numOfBlksRead, bufBlockDat, nSize, ref bytesBlkDatRead) : 
                MKReader32.ISO15693_ReadMultiBlocks32(readSecSta, nBlkAddr, numOfBlksToRead, ref numOfBlksRead, bufBlockDat, nSize, ref bytesBlkDatRead); }

        public static int ISO15693_WriteMultipleBlocks(int blkAddr, int numOfBlks, byte[] newBlkData, int bytesToWrite)
        { return is64bit ? MKReader64.ISO15693_WriteMultipleBlocks64(blkAddr, numOfBlks, newBlkData, bytesToWrite) : 
                MKReader32.ISO15693_WriteMultipleBlocks32(blkAddr, numOfBlks, newBlkData, bytesToWrite); }

        public static int ISO15693_GetBlockSecStatus(int blkAddr, int numOfBlks, byte[] bufBlkSecs, int nSize, ref int bytesSecRead)
        { return is64bit ? MKReader64.ISO15693_GetBlockSecStatus64(blkAddr, numOfBlks, bufBlkSecs, nSize, ref bytesSecRead) : 
                MKReader32.ISO15693_GetBlockSecStatus32(blkAddr, numOfBlks,  bufBlkSecs, nSize, ref bytesSecRead); }

        public static int ISO15693_GetSystemInfo(byte[] uid, ref byte dsfid, ref byte afi, ref int blkSize, ref int numOfBloks, ref byte icRef)
        { return is64bit ? MKReader64.ISO15693_GetSystemInfo64(uid, ref dsfid, ref afi, ref blkSize, ref numOfBloks, ref icRef) : 
                MKReader32.ISO15693_GetSystemInfo32(uid, ref dsfid, ref afi, ref blkSize, ref numOfBloks, ref icRef); }

        public static int ISO15693_LockMultipleBlocks(int blkAddr, int numOfBlks)
        { return is64bit ? MKReader64.ISO15693_LockMultipleBlocks64(blkAddr, numOfBlks) : MKReader32.ISO15693_LockMultipleBlocks32(blkAddr, numOfBlks); }

        public static int ISO15693_WriteAFI(byte afi)
        { return is64bit ? MKReader64.ISO15693_WriteAFI64(afi) : MKReader32.ISO15693_WriteAFI32(afi); }

        public static int ISO15693_LockAFI()
        { return is64bit ? MKReader64.ISO15693_LockAFI64() : MKReader32.ISO15693_LockAFI32(); }

        public static int ISO15693_WriteDSFID(byte dsfid)
        { return is64bit ? MKReader64.ISO15693_WriteDSFID64(dsfid) : MKReader32.ISO15693_WriteDSFID32(dsfid); }

        public static int ISO15693_LockDSFID()
        { return is64bit ? MKReader64.ISO15693_LockDSFID64() : MKReader32.ISO15693_LockDSFID32(); }

        public static int ISO15693_Inventory(byte afi, byte[] bufUids, int nSize, ref int bytesUidNums)
        { return is64bit ? MKReader64.ISO15693_Inventory64(afi, bufUids, nSize, ref bytesUidNums) : MKReader32.ISO15693_Inventory32(afi, bufUids, nSize, ref bytesUidNums); }
        #endregion
        
        #region MIFARE卡相关函数
        //---------------------------------------------------------------------------
        //MIFARE卡相关函数
        //---------------------------------------------------------------------------
        public static int MIFARE_Authentication(byte bSectorNo, byte[] pbKeyA, byte[] pbKeyB)
        { return is64bit ? MKReader64.MIFARE_Authentication64(bSectorNo, pbKeyA, pbKeyB) : MKReader32.MIFARE_Authentication32(bSectorNo, pbKeyA, pbKeyB); }

        public static int MIFARE_ReadData(byte bBlock, byte[] data, int nLen)
        { return is64bit ? MKReader64.MIFARE_ReadData64(bBlock, data, nLen) : MKReader32.MIFARE_ReadData32(bBlock, data, nLen); }

        public static int MIFARE_WrtieData(byte bBlock, byte[] data, int nLen)
        { return is64bit ? MKReader64.MIFARE_WrtieData64(bBlock, data, nLen) : MKReader32.MIFARE_WrtieData32(bBlock, data, nLen); }

        public static int MIFARE_IncrementValue(byte bBlock, int nValue)
        { return is64bit ? MKReader64.MIFARE_IncrementValue64(bBlock, nValue) : MKReader32.MIFARE_IncrementValue32(bBlock, nValue); }

        public static int MIFARE_DecrementValue(byte bBlock, int nValue)
        { return is64bit ? MKReader64.MIFARE_DecrementValue64(bBlock, nValue) : MKReader32.MIFARE_DecrementValue32(bBlock, nValue); }

        public static int MIFARE_ReadValue(byte bBlock, ref int pnValue)
        { return is64bit ? MKReader64.MIFARE_ReadValue64(bBlock, ref pnValue) : MKReader32.MIFARE_ReadValue32(bBlock, ref pnValue); }

        public static int MIFARE_InitValue(byte bBlock, int nValue)
        { return is64bit ? MKReader64.MIFARE_InitValue64(bBlock, nValue) : MKReader32.MIFARE_InitValue32(bBlock, nValue); }

        public static int MIFARE_WriteSectorTrailer(byte bBlock, byte[] pbKEYA, byte[] pbKEYB, byte[] pbAccessBits)
        { return is64bit ? MKReader64.MIFARE_WriteSectorTrailer64(bBlock, pbKEYA, pbKEYB, pbAccessBits) : 
                MKReader32.MIFARE_WriteSectorTrailer32(bBlock, pbKEYA, pbKEYB, pbAccessBits); }
        #endregion

        #region 第二代居民身份证
        public static bool GetName(byte[] sName, ref int nLen)
        { return is64bit ? MKReader64.GetName64(sName, ref nLen) : MKReader32.GetName32(sName, ref nLen); }

        public static bool GetSex(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetSex64(sBuf, ref nLen) : MKReader32.GetSex32(sBuf, ref nLen); }

        public static bool GetNation(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetNation64(sBuf, ref nLen) : MKReader32.GetNation32(sBuf, ref nLen); }

        public static bool GetBornDate(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetBornDate64(sBuf, ref nLen) : MKReader32.GetBornDate32(sBuf, ref nLen); }

        public static bool GetAddress(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetAddress64(sBuf, ref nLen) : MKReader32.GetAddress32(sBuf, ref nLen); }

        public static bool GetIDNo(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetIDNo64(sBuf, ref nLen) : MKReader32.GetIDNo32(sBuf, ref nLen); }

        public static bool GetSignGov(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetSignGov64(sBuf, ref nLen) : MKReader32.GetSignGov32(sBuf, ref nLen); }

        public static bool GetStartDate(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetStartDate64(sBuf, ref nLen) : MKReader32.GetStartDate32(sBuf, ref nLen); }

        public static bool GetEndDate(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetEndDate64(sBuf, ref nLen) : MKReader32.GetEndDate32(sBuf, ref nLen); }

        public static bool GetNewAddress(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetEndDate64(sBuf, ref nLen) : MKReader32.GetEndDate32(sBuf, ref nLen); }       

        public static bool GetFingerPrint(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFingerPrint64(sBuf, ref nLen) : MKReader32.GetFingerPrint32(sBuf, ref nLen); }
                
        public static bool MakeIDCardImages(string sHead, string sIDCardImageFace, string sIDCardImageBack)
        { return is64bit ? MKReader64.MakeIDCardImages64(sHead, sIDCardImageFace, sIDCardImageBack) : MKReader32.MakeIDCardImages32(sHead, sIDCardImageFace, sIDCardImageBack); }

        public static bool GetPhoto(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetPhoto64(sBuf, ref nLen) : MKReader32.GetPhoto32(sBuf, ref nLen); }
        #endregion

        #region 外国人永久居住证
        public static int IsFPRIDCard()
        { return is64bit ? MKReader64.IsFPRIDCard64() : MKReader32.IsFPRIDCard32(); }//是否是外国人居住证

        public static bool GetFPR_ENName(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_ENName64(sBuf, ref nLen) : MKReader32.GetFPR_ENName32(sBuf, ref nLen); }//英文名

        public static bool GetFPR_SEX(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_SEX64(sBuf, ref nLen) : MKReader32.GetFPR_SEX32(sBuf, ref nLen); }//性别

        public static bool GetFPR_IDNo(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_IDNo64(sBuf, ref nLen) : MKReader32.GetFPR_IDNo32(sBuf, ref nLen); }//身份证号

        public static bool GetFPR_NationCode(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_NationCode64(sBuf, ref nLen) : MKReader32.GetFPR_NationCode32(sBuf, ref nLen); }//国籍代码

        public static bool GetFPR_Nation(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_Nation64(sBuf, ref nLen) : MKReader32.GetFPR_Nation32(sBuf, ref nLen); }//国籍代码中文()

        public static bool GetFPR_CHNName(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_CHNName64(sBuf, ref nLen) : MKReader32.GetFPR_CHNName32(sBuf, ref nLen); }//中文姓名

        public static bool GetFPR_ValidStartDate(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_ValidStartDate64(sBuf, ref nLen) : MKReader32.GetFPR_ValidStartDate32(sBuf, ref nLen); }//证件签发时间

        public static bool GetFPR_ValidEndDate(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_ValidEndDate64(sBuf, ref nLen) : MKReader32.GetFPR_ValidEndDate32(sBuf, ref nLen); }//证件终止时间

        public static bool GetFPR_Birthday(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_Birthday64(sBuf, ref nLen) : MKReader32.GetFPR_Birthday32(sBuf, ref nLen); }//出生日期

        public static bool GetFPR_IDVersion(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_IDVersion64(sBuf, ref nLen) : MKReader32.GetFPR_IDVersion32(sBuf, ref nLen); }//证件版本号

        public static bool GetFPR_IssuingAuthorityCode(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_IssuingAuthorityCode64(sBuf, ref nLen) : MKReader32.GetFPR_IssuingAuthorityCode32(sBuf, ref nLen); }//当次申请受理机关代码

        public static bool GetFPR_IDType(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR_IDType64(sBuf, ref nLen) : MKReader32.GetFPR_IDType32(sBuf, ref nLen); }//证件类型标识
        #endregion

        #region 新版外国人永久居住证相关函数
        public static int IsFPR2IDCard()
        { return is64bit ? MKReader64.IsFPR2IDCard64() : MKReader32.IsFPR2IDCard32(); }//是否是外国人居住证

        public static bool GetFPR2_Sex(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_Sex64(sBuf, ref nLen) : MKReader32.GetFPR2_Sex32(sBuf, ref nLen); }//性别

        public static bool GetFPR2_SexCode(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_SexCode64(sBuf, ref nLen) : MKReader32.GetFPR2_SexCode32(sBuf, ref nLen); }//性别

        public static bool GetFPR2_NationCode(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_NationCode64(sBuf, ref nLen) : MKReader32.GetFPR2_NationCode32(sBuf, ref nLen); }//国籍代码

        public static bool GetFPR2_Nation(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_Nation64(sBuf, ref nLen) : MKReader32.GetFPR2_Nation32(sBuf, ref nLen); }//国籍代码中文()

        public static bool GetFPR2_ValidStartDate(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_ValidStartDate64(sBuf, ref nLen) : MKReader32.GetFPR2_ValidStartDate32(sBuf, ref nLen); }//证件签发时间

        public static bool GetFPR2_ValidEndDate(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_ValidEndDate64(sBuf, ref nLen) : MKReader32.GetFPR2_ValidEndDate32(sBuf, ref nLen); }//证件终止时间

        public static bool GetFPR2_Birthday(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_Birthday64(sBuf, ref nLen) : MKReader32.GetFPR2_Birthday32(sBuf, ref nLen); }//出生日期

        public static bool GetFPR2_ENName(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_ENName64(sBuf, ref nLen) : MKReader32.GetFPR2_ENName32(sBuf, ref nLen); }//英文名

        public static bool GetFPR2_ENNameB(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_ENNameB64(sBuf, ref nLen) : MKReader32.GetFPR2_ENNameB32(sBuf, ref nLen); }//英文名

        public static bool GetFPR2_CHNName(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_CHNName64(sBuf, ref nLen) : MKReader32.GetFPR2_CHNName32(sBuf, ref nLen); }//中文姓名

        public static bool GetFPR2_IDNo(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_IDNo64(sBuf, ref nLen) : MKReader32.GetFPR2_IDNo32(sBuf, ref nLen); }//身份证号

        public static bool GetFPR2_IDType(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_IDType64(sBuf, ref nLen) : MKReader32.GetFPR2_IDType32(sBuf, ref nLen); }//证件类型标识

        public static bool GetFPR2_ReserveA(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_ReserveA64(sBuf, ref nLen) : MKReader32.GetFPR2_ReserveA32(sBuf, ref nLen); }//证件类型标识

        public static bool GetFPR2_ReserveB(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_ReserveB64(sBuf, ref nLen) : MKReader32.GetFPR2_ReserveB32(sBuf, ref nLen); }//证件类型标识

        public static bool GetFPR2_RenewalTimes(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetFPR2_RenewalTimes64(sBuf, ref nLen) : MKReader32.GetFPR2_RenewalTimes32(sBuf, ref nLen); }
        #endregion

        #region 港澳台居民居住证
        //---------------------------------------------------------------------------
        public static int IsGATIDCard()
        { return is64bit ? MKReader64.IsGATIDCard64() : MKReader32.IsGATIDCard32(); }//是否港澳台居民居住证

        public static bool GetGAT_Name(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_Name64(sBuf, ref nLen) : MKReader32.GetGAT_Name32(sBuf, ref nLen); }//姓名

        public static bool GetGAT_SEX(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_SEX64(sBuf, ref nLen) : MKReader32.GetGAT_SEX32(sBuf, ref nLen); }//性别

        public static bool GetGAT_SEXCode(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_SEXCode64(sBuf, ref nLen) : MKReader32.GetGAT_SEXCode32(sBuf, ref nLen); }//性别代码

        public static bool GetGAT_Address(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_Address64(sBuf, ref nLen) : MKReader32.GetGAT_Address32(sBuf, ref nLen); }//详细地址

        public static bool GetGAT_IDNo(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_IDNo64(sBuf, ref nLen) : MKReader32.GetGAT_IDNo32(sBuf, ref nLen); }//公民身份证号码

        public static bool GetGAT_IssuingAuthority(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_IssuingAuthority64(sBuf, ref nLen) : MKReader32.GetGAT_IssuingAuthority32(sBuf, ref nLen); }//签发机关

        public static bool GetGAT_ValidStartDate(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_ValidStartDate64(sBuf, ref nLen) : MKReader32.GetGAT_ValidStartDate32(sBuf, ref nLen); }//有效起始日期

        public static bool GetGAT_ValidEndDate(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_ValidEndDate64(sBuf, ref nLen) : MKReader32.GetGAT_ValidEndDate32(sBuf, ref nLen); }//有效截至日期

        public static bool GetGAT_PassportNo(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_PassportNo64(sBuf, ref nLen) : MKReader32.GetGAT_PassportNo32(sBuf, ref nLen); }//通行证号码(

        public static bool GetGAT_IssuanceCount(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_IssuanceCount64(sBuf, ref nLen) : MKReader32.GetGAT_IssuanceCount32(sBuf, ref nLen); }//签发次数

        public static bool GetGAT_IDType(byte[] sBuf, ref int nLen)
        { return is64bit ? MKReader64.GetGAT_IDType64(sBuf, ref nLen) : MKReader32.GetGAT_IDType32(sBuf, ref nLen); }//证件类型标识(2B),大写字母J

        #endregion
        #endregion
        
        public static string GetSAMNo()
        {
            byte[] bySAMID = new byte[100];
            int nRet = IDCardReader.GetSAMID(bySAMID);
            if (nRet == 0)
                return System.Text.Encoding.GetEncoding("GB2312").GetString(bySAMID);
            return string.Empty;
        }

        public static bool TransCommand(ReaderSlotNum nReaderSlot, string sReq, out string sResp)
        {
            byte[] bySendData = StrToHexByte(sReq);
            byte[] byRecvData = new byte[270];
            int nLen = 0;
            int nRet = IDCardReader.TransApduCommand(nReaderSlot, bySendData, bySendData.Length, byRecvData, ref nLen);

            sResp = "";
            if (nRet != 0 || (byRecvData[0] != 0x00 && byRecvData[1] != 0x00))
            {
                sResp = HexByteToStr(byRecvData, nLen);//nRet.ToString({return 0;}
                return false;
            }
            byte[] byRecvData2 = new byte[nLen - 2];
            Array.Copy(byRecvData, 2, byRecvData2, 0, nLen - 2);
            sResp = HexByteToStr(byRecvData2, nLen - 2);
            return true;
        }

        public static string GetFwVersion()
        {
            string sGetVersion = "31 14";
            byte[] bySendData;
            byte[] byRecvData = new byte[200];
            int nLen = 0;
            bySendData = StrToHexByte(sGetVersion);
            int nRet = IDCardReader.TransApduCommand(0, bySendData, bySendData.Length, byRecvData, ref nLen);
            if (nRet == 0)
            {
                int m = byRecvData[2];
                int n = byRecvData[3];
                int o = byRecvData[4];
                String devVer = string.Format("{0:0}.{1:0}.{2:0}.{3:0}", byRecvData[2], byRecvData[3], byRecvData[4], byRecvData[5]);
                //string sVersion = "Ver " + m + "." + n + "." + o;
                return devVer;
            }
            return "";
        }

        public static int ActivateCard(ReaderSlotNum nReaderSlot, ref byte byAnt, byte[] pRecvDatas, ref int nRecvLen)
        {
            int nRet;
            SetAntPower(0);
            nRet = ActivateCard(nReaderSlot, pRecvDatas, ref nRecvLen);
            if (nRet != 0)
            {
                SetAntPower(0x10);
                nRet = ActivateCard(nReaderSlot,  pRecvDatas, ref nRecvLen);
                if (nRet == 0)  byAnt = 2;
            } else byAnt = 1;
            return nRet;
        }
        
        public static bool TransApdu(ReaderSlotNum nReaderSlot, string sReq, out string sResp)
        {
            byte[] bySendData = StrToHexByte(sReq);
            byte[] byRecvData = new byte[270];
            int nLen = 0;
            int nRet = IDCardReader.ISO14443_TransApdu(nReaderSlot, bySendData, bySendData.Length, byRecvData, ref nLen);

            sResp = "";
            if (nRet != 0)
            {
                sResp = nRet.ToString();
                return false;
            }
            sResp = HexByteToStr(byRecvData, nLen);
            return true;
        }

        public static int Read_Content(int active, long delayMs)
        {
            int nRet = 0;
            Stopwatch stopWatch = null;
            try
            {
                stopWatch = new Stopwatch();
                stopWatch.Start();

                while (true)
                {
                    System.Windows.Forms.Application.DoEvents();
                    if (stopWatch.ElapsedMilliseconds > delayMs) return -8;
                    nRet = Authenticate();
                    if (nRet == 0)
                    {
                        nRet = Read_Content(1);
                        if (nRet != 0)
                        {
                            System.Threading.Thread.Sleep(300);
                            continue;
                        }
                        return 0;
                    }
                }
            }
            catch { }
            finally
            {
                if(stopWatch != null)stopWatch.Stop();
            }
            return nRet;
        }

        #region 工具函数
        public static byte[] StrToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }

        public static string HexByteToStr(byte[] hexbytes, int bytelen)
        {
            string formattext = "";
            for (int myi = 0; myi < bytelen; myi++)
            {
                formattext += string.Format("{0:X2}", hexbytes[myi]);
            }
            return formattext;
        }


        public static byte[] StrToByteArray(string str)
        {
            ASCIIEncoding encoding = new ASCIIEncoding();
            return encoding.GetBytes(str);
        }

        public static string ByteArrayToStr(byte[] barr)
        {
            System.Text.UnicodeEncoding encoding = new UnicodeEncoding();
            return encoding.GetString(barr);
        }
        #endregion
    }

    #region 工具类
    public static class Utils
    {
        public static byte[] StrToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }

        public static int HexStrToInt(string hexstr)
        {
            /*
            string strTmp = hexstr.Replace(" ","");
            if (strTmp.Length > 0)
                return Int32.Parse(strTmp, System.Globalization.NumberStyles.HexNumber);
             */
            //创建两个不同的encoding对象
            Encoding unicode = Encoding.Unicode;
            //创建GBK码对象
            Encoding gbk = Encoding.GetEncoding(936);
            byte[] hexBytes = StrToHexByte(hexstr);
            byte[] unicodeBytes = Encoding.Convert(gbk, unicode, hexBytes, 0, hexBytes.Length);
            string strInt = System.Text.Encoding.Unicode.GetString(unicodeBytes, 0, unicodeBytes.Length);
            return Int32.Parse(strInt);
        }

        public static string HexStrToAsc(string hexstr)
        {
            //创建两个不同的encoding对象
            Encoding unicode = Encoding.Unicode;
            //创建GBK码对象
            Encoding gbk = Encoding.GetEncoding(936);
            byte[] hexBytes = StrToHexByte(hexstr);
            byte[] unicodeBytes = Encoding.Convert(gbk, unicode, hexBytes, 0, hexBytes.Length);
            return System.Text.Encoding.Unicode.GetString(unicodeBytes, 0, unicodeBytes.Length);
        }

        public static string HexByteToStr(byte[] hexbytes, int bytelen)
        {
            string formattext = "";
            for (int myi = 0; myi < bytelen; myi++)
            {
                formattext += string.Format("{0:X2}", hexbytes[myi]);
            }
            return formattext;
        }

        public static string ASCToHexStr(string ascString)
        {
            string formattext = "";
            for (int myi = 0; myi < ascString.Length; myi++)
            {
                formattext += string.Format("{0:X2} ", (byte)ascString[myi]);
            }
            return formattext;
        }
    }

    public class TLV
    {
        public byte[] Tag { get; set; }
        public byte[] Length { get; set; }
        public byte[] Value { get; set; }
        public int TagSize { get { return this.Tag.Length; } }
        public int LengthSize { get { return this.Length.Length; } }
        public List<TLV> SubTLVEntity { get; set; }
    }

    public class TLVHelper
    {
        public static List<TLV> Construct(byte[] buffer)
        {
            List<TLV> resultList = new List<TLV>();
            int currentIndex = 0;
            while (currentIndex < buffer.Length)
            {
                TLV entity = new TLV();
                bool hasSubEntity = HasSubEntity(buffer, currentIndex);
                entity.Tag = GetTag(buffer, currentIndex);
                currentIndex += entity.Tag.Length;
                entity.Length = GetLength(buffer, currentIndex);
                currentIndex += entity.Length.Length;
                int valueLength = GetValueLengthByLengthByteValue(entity.Length);
                entity.Value = buffer.Take(currentIndex + valueLength).Skip(currentIndex).ToArray();
                if (hasSubEntity)
                    entity.SubTLVEntity = Construct(entity.Value);
                currentIndex += entity.Value.Length;
                resultList.Add(entity);
            }
            return resultList;
        }

        private static bool HasSubEntity(byte[] bytes, int index)
        {
            if (bytes.Length < index + 1) throw new ArgumentException("无效的索引值");
            return (bytes[index] & 0x20) == 0x20;
        }

        private static byte[] GetTag(byte[] bytes, int index)
        {
            if (bytes.Length < index + 1)
                throw new ArgumentException("无效的索引值");
            if ((bytes[index] & 0x1f) == 0x1f)
            {
                return new byte[] { bytes[index], bytes[index + 1] };
            }
            else
            {
                return new byte[] { bytes[index] };
            }
        }

        private static byte[] GetLength(byte[] bytes, int index)
        {
            if (bytes.Length < index + 1)
                throw new ArgumentException("无效的索引值");
            if ((bytes[index] & 0x80) == 0x80)
            {
                int lengthSize = (bytes[index] & 0x7f) + 1;
                return bytes.Take(index + lengthSize).Skip(index).ToArray();
            }
            else
            {
                return new byte[] { bytes[index] };
            }
        }
        private static int GetValueLengthByLengthByteValue(byte[] bytes)
        {
            int length = 0;
            if (bytes.Length == 1)
                length = bytes[0];
            else
            {
                for (int index = 1; index < bytes.Length; index++)
                {
                    length += bytes[index] << ((index - 1) * 8);
                }
            }
            return length;
        }
        public static byte[] Parse(List<TLV> list)
        {
            byte[] buffer = new byte[4096];
            int currentIndex = 0;
            int currentTLVIndex = 0;
            int valueSize = 0;

            while (currentTLVIndex < list.Count())
            {
                valueSize = 0;
                TLV entity = list[currentTLVIndex];

                Array.Copy(entity.Tag, 0, buffer, currentIndex, entity.TagSize);

                currentIndex += entity.TagSize;

                for (int index = 0; index < entity.LengthSize; index++)
                {
                    valueSize += entity.Length[index] << (index * 8);
                }
                if (valueSize > 127)
                {
                    buffer[currentIndex] = Convert.ToByte(0x80 | entity.LengthSize);
                    currentIndex += 1;
                }

                Array.Copy(entity.Length, 0, buffer, currentIndex, entity.LengthSize);

                currentIndex += entity.LengthSize;
                if (entity.SubTLVEntity == null)
                {
                    Array.Copy(entity.Value, 0, buffer, currentIndex, valueSize);
                    currentIndex += valueSize;
                }
                else
                {
                    byte[] tempBuffer = Parse(entity.SubTLVEntity);
                    Array.Copy(tempBuffer, 0, buffer, currentIndex, tempBuffer.Length);
                    currentIndex += tempBuffer.Length;
                }
                currentTLVIndex++;
            }

            byte[] resultBuffer = new byte[currentIndex];
            Array.Copy(buffer, 0, resultBuffer, 0, currentIndex);
            return resultBuffer;
        }

        public static TLV GetValueByTag(List<TLV> entities, string tag)
        {
            TLV resultEntity = null;
            var query = entities.SingleOrDefault(e => ToHexString(e.Tag).ToUpper() == tag);
            if (query == null)
            {
                foreach (var tlv in entities)
                {
                    if (tlv.SubTLVEntity != null)
                    {
                        TLV result = GetValueByTag(tlv.SubTLVEntity, tag);

                        if (result != null && result.Length.Length > 0)
                            return result;
                    }
                }
            }
            else
                resultEntity = query;
            return resultEntity;
        }
        public static List<TLV> ToTLVEntityList(string data)
        {
            byte[] dataBytes = HexStringToByteArray(data);
            var tlvList = Construct(dataBytes);
            return tlvList;
        }
        public static List<TLV> ToTLVEntityList(byte[] dataBytes)
        {
            var tlvList = Construct(dataBytes);
            return tlvList;
        }

        public static byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
            {
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            }
            return buffer;
        }
        public static string ToHexString(byte[] dataBytes)
        {
            string returnStr = "";
            if (dataBytes != null)
            {
                for (int i = 0; i < dataBytes.Length; i++)
                {
                    returnStr += dataBytes[i].ToString("X2");
                }
            }
            return returnStr;
        }
    }
    #endregion
}
