浏览代码

#IQRV #comment [Vendor] 上传南天代码

gifur 4 年之前
父节点
当前提交
9de3dd6c57

+ 18 - 0
DevAdapter/nantian/CMakeLists.txt

@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(nantian C CXX)
+
+set(CMAKE_COLOR_MAKEFILE ON)
+
+# VENDOR_CURRENT_{DEPS|INCLUDE|ASSET|LIB|BIN}_DIR 等定义已集成到该宏内
+rvc_define_dependen_dirs()
+
+# 遍历当前目录下带有CMakeLists.txt文件的文件夹
+rvc_traverse_sub_cmake_dirs()
+
+#  =-=-=-=-=-=-=-=-=-= {VendorName}/CMakeLists.txt 文件最后必须声明如下内容=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=
+rvc_aggereate_runtime_file()
+
+
+
+

+ 25 - 0
DevAdapter/nantian/FingerPrint.1.1/CMakeLists.txt

@@ -0,0 +1,25 @@
+# 声明模块名称的前缀和名称
+rvc_dev_define_module("FingerPrint")
+
+# rvc_dev_config_library 内需要使用这三个参数,用于拼接输出的适配器文件名称
+set(${MODULE_PREFIX}_VENDOR "nantian")
+set(${MODULE_PREFIX}_VERSION "1")
+set(${MODULE_PREFIX}_BATCH "1")
+
+# 包含要编译的实现文件,rvc_dev_config_library 内使用
+set(${MODULE_PREFIX}_SRCS SHARED
+	fingerprint.nantian.1.1.cpp
+    Gvar.cpp
+)
+
+# 适配器工程需要通过此宏替代 add_library
+rvc_dev_config_library(${MODULE_NAME} ${MODULE_PREFIX})
+
+# ${MODULE_FULL_NAME} 是 TAGET 名称,在 rvc_dev_config_library 中定义
+target_include_directories(${MODULE_FULL_NAME} PRIVATE "${VENDOR_CURRENT_INCLUDE_DIR}")
+target_link_directories(${MODULE_FULL_NAME} PRIVATE "${VENDOR_CURRENT_LIB_DIR}")
+
+#target_link_libraries(${MODULE_FULL_NAME} demo)
+
+#  =-=-=-=-=-=-=-=-=-= {适配器工程}/CMakeLists.txt 文件最后必须声明如下内容=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=
+rvc_dev_target_install(${MODULE_FULL_NAME})

+ 213 - 0
DevAdapter/nantian/FingerPrint.1.1/Gvar.cpp

@@ -0,0 +1,213 @@
+// Gvar.cpp: implementation of the Gvar class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "Gvar.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+Gvar::Gvar()
+{
+	m_hDll1 = NULL;
+	m_isLoad = FALSE;
+	m_trace = NULL;
+	m_trace = new CILIXTrace(NULL,"FingerPrint","fingerprint.nantian.1.1");
+	m_connect = FALSE;
+	m_cancel = FALSE;
+	FPIGetHdrVer = NULL;
+	FPIGetFrwVer = NULL;
+	FPIChkPressed = NULL;
+	FPIGetDevSN = NULL;
+	FPIFindDevice = NULL;
+	FPIGetFeature = NULL;
+	FPIGetImageDat = NULL;
+	FPIRawToBmp = NULL;
+	FPISaveImage = NULL;
+	FPIFeaFrmImg = NULL;
+	FPITplFrmImg = NULL;
+	FPIFpMatch = NULL;
+	FPICloseDevice = NULL;
+	FPITplFrmImgBmp = NULL;
+	m_port = 0;
+	LoadDll();
+}
+
+Gvar::~Gvar()
+{
+	if (m_hDll1 != NULL)
+	{
+		FreeDll();
+	}
+	if (m_trace)
+	{
+		delete m_trace;
+		m_trace = NULL;
+	}
+}
+void Gvar::LoadDll()
+{
+	char confile[1024] = "";
+	CILIX_AUX_X::CILIX_GetModuleCurPath(confile);
+	char dll1Path[1024] = "";
+	strcpy(dll1Path,confile);
+	memset(m_image,0,sizeof(m_image));
+	strcpy(m_image,confile);
+	strcat(dll1Path,"libusbfpex64.nantian.so");
+	m_trace->WriteTrace(CILIXTRACE_L_INFO,"LoadDll","版本:V1.0.0.6");
+	m_trace->WriteTrace(CILIXTRACE_L_INFO,"LoadDll","驱动库路径dll1Path=%s",dll1Path);
+	m_hDll1 = dlopen(dll1Path,RTLD_LAZY);
+	if (m_hDll1 == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库“libusbfpex64.nantian.so”加载失败");
+		return;
+	}
+	FPIGetHdrVer = (PFPIGetHdrVer)dlsym(m_hDll1,"FPIGetHdrVer");
+	if (FPIGetHdrVer == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPIGetHdrVer加载失败");
+		return;
+	}
+	FPIGetFrwVer = (PFPIGetFrwVer)dlsym(m_hDll1,"FPIGetFrwVer");
+	if (FPIGetFrwVer == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPIGetFrwVer加载失败");
+		return;
+	}
+	FPIChkPressed = (PFPIChkPressed)dlsym(m_hDll1,"FPIChkPressed");
+	if (FPIChkPressed == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPIChkPressed加载失败");
+		return;
+	}
+	FPIGetDevSN = (PFPIGetDevSN)dlsym(m_hDll1,"FPIGetDevSN");
+	if (FPIGetDevSN == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPIGetDevSN加载失败");
+		return;
+	}
+	FPIFindDevice = (PFPIFindDevice)dlsym(m_hDll1,"FPIFindDevice");
+	if (FPIFindDevice == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPIFindDevice加载失败");
+		return;
+	}
+	FPIGetFeature = (PFPIGetFeature)dlsym(m_hDll1,"FPIGetFeature");
+	if (FPIGetFeature == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPIGetFeature加载失败");
+		return;
+	}
+	FPIGetImageDat = (PFPIGetImageDat)dlsym(m_hDll1,"FPIGetImageDat");
+	if (FPIGetImageDat == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPIGetImageDat加载失败");
+		return;
+	}
+	FPIRawToBmp = (PFPIRawToBmp)dlsym(m_hDll1,"FPIRawToBmp");
+	if (FPIRawToBmp == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPIRawToBmp加载失败");
+		return;
+	}
+	FPISaveImage = (PFPISaveImage)dlsym(m_hDll1,"FPISaveImage");
+	if (FPISaveImage == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPISaveImage加载失败");
+		return;
+	}
+	FPIFeaFrmImg = (PFPIFeaFrmImg)dlsym(m_hDll1,"FPIFeaFrmImg");
+	if (FPIFeaFrmImg == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPIFeaFrmImg加载失败");
+		return;
+	}
+	FPITplFrmImg = (PFPITplFrmImg)dlsym(m_hDll1,"FPITplFrmImg");
+	if (FPITplFrmImg == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPITplFrmImg加载失败");
+		return;
+	}
+	FPIFpMatch = (PFPIFpMatch)dlsym(m_hDll1,"FPIFpMatch");
+	if (FPIFpMatch == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPIFpMatch加载失败");
+		return;
+	}
+	FPICloseDevice = (PFPICloseDevice)dlsym(m_hDll1,"FPICloseDevice");
+	if (FPICloseDevice == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPICloseDevice加载失败");
+		return;
+	}
+	FPITplFrmImgBmp = (PFPITplFrmImgBmp)dlsym(m_hDll1,"FPITplFrmImgBmp");
+	if (FPITplFrmImgBmp == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadDll","动态库函数FPITplFrmImgBmp加载失败");
+		return;
+	}
+	m_isLoad = TRUE;
+	m_trace->WriteTrace(CILIXTRACE_L_INFO,"LoadDll","动态库加载成功退出接口");
+	return ;
+}
+void Gvar::FreeDll()
+{
+	if (m_hDll1)
+	{
+		dlclose(m_hDll1);
+		m_hDll1 = NULL;
+	}
+}
+int Gvar::WriteFileEx(char *filename, char *Value, int ValueLen)
+{
+	FILE *fp;
+
+	if(NULL == (fp = fopen(filename, "w+"))) {
+		perror("fopen");
+		return -1;
+	}
+
+	fwrite(Value, 1, ValueLen, fp);
+
+	fclose(fp);
+	return 0;
+}
+
+int Gvar::ReadFileEx(char *filename, char *Value, int *ValueLen)
+{
+	FILE *fp;
+
+	if(NULL == (fp = fopen(filename, "r"))) {
+		perror("fopen");
+		return -1;
+	}
+
+	fseek(fp, 0L, SEEK_END);
+	*ValueLen = ftell(fp);
+
+	fseek(fp, 0L, SEEK_SET);
+	int f = fread(Value, 1,  *ValueLen, fp);
+
+	fclose(fp);
+	return 0;
+}
+
+void Gvar::CreateFileEx(char* path,char* data,int ilen)
+{
+	int i = 0;
+	char FilePath[100] = "";
+	FilePath[0] = path[0];
+	for(i= 1; i<=strlen(path); i++)
+	{
+		FilePath[i] = path[i];
+		if(path[i] == '/')
+		{
+			if(access(FilePath, F_OK) != 0)
+			{
+				mkdir(FilePath,S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IRWXO);
+			}
+		}
+	}
+	WriteFileEx(FilePath,data,ilen);
+}

+ 84 - 0
DevAdapter/nantian/FingerPrint.1.1/Gvar.h

@@ -0,0 +1,84 @@
+// Gvar.h: interface for the Gvar class.
+//
+//////////////////////////////////////////////////////////////////////
+
+
+#include "./CILIX_AUX_UTILS.h"
+
+
+/*---获取硬件版本---*/
+typedef int (*PFPIGetHdrVer)(int nPort, char * pszHdrVer);
+
+/*---获取设备固件版本---*/
+typedef int (*PFPIGetFrwVer)(int nPort, char * pszFrwVer);
+
+/*---判断手指是否按捺---*/
+typedef int (*PFPIChkPressed)(int nPort);
+
+/*---获取指纹仪SN序号---*/
+typedef int (*PFPIGetDevSN)(int nPort, char * pszDevSN);
+
+/*---检测有没有连接指纹---*/
+typedef int (*PFPIFindDevice)(int nPort, char * pszDevName);
+
+/*----获取指纹特征数据---*/
+typedef int (*PFPIGetFeature)(int nPort, char * pszVer);
+
+/*---获取指纹图片---*/
+typedef int (*PFPIGetImageDat)(int nPort, char * psImg);
+
+/*---raw转bmp---*/
+typedef int (*PFPIRawToBmp)(unsigned char *pRawBuf,unsigned char *pBmpBuf,int *pnBmpLen);
+
+/*---保存指纹图像---*/
+typedef int (*PFPISaveImage)(char *pPath,char *pImgBuf);
+
+/*---提取特征---*/
+typedef int (*PFPIFeaFrmImg)(char *pImgBuf, char *pVerBuf, int *pnVerLen);
+
+/*---FPITplFrmImg由三张指纹图像(即 FPIGetImageDat 获取的图像数据)合成一枚指纹模板数据特征---*/
+typedef int (*PFPITplFrmImg)(char *pImgBuf1, char * pImgBuf2,char *pImgBuf3, char *pRegBuf, int *pnRegLen);
+
+/*---指纹比对---*/
+typedef int (*PFPIFpMatch)(char * pszReg, char * pszVer, int nMatchLevel);
+
+/*---关闭设备(无实际作用)---*/
+typedef int (*PFPICloseDevice)(int nPort);
+
+typedef int (*PFPITplFrmImgBmp)(char *pBmpPath1, char * pBmpPath2,char *pBmpPath3, char *pRegBuf, int *pnRegLen);
+
+class Gvar  
+{
+public:
+	Gvar();
+	virtual ~Gvar();
+	void LoadDll();
+	void FreeDll();
+	int WriteFileEx(char *filename, char *Value, int ValueLen);
+	int ReadFileEx(char *filename, char *Value, int *ValueLen);
+	void CreateFileEx(char* path,char* data,int ilen);
+public:
+	void* m_hDll1;//加载动态库句柄
+	BOOL m_isLoad;//动态库是否加载成功标志
+	CILIXTrace *m_trace;//日志
+	BOOL m_connect;
+	BOOL m_cancel;
+	int m_port;
+	char m_image[1024];
+
+	PFPIGetHdrVer   FPIGetHdrVer;
+	PFPIGetFrwVer   FPIGetFrwVer;
+	PFPIChkPressed  FPIChkPressed;
+	PFPIGetDevSN    FPIGetDevSN;
+	PFPIFindDevice  FPIFindDevice;
+	PFPIGetFeature  FPIGetFeature;
+	PFPIGetImageDat FPIGetImageDat;
+	PFPIRawToBmp    FPIRawToBmp;
+	PFPISaveImage   FPISaveImage;
+	PFPIFeaFrmImg   FPIFeaFrmImg;
+	PFPITplFrmImg   FPITplFrmImg;
+	PFPIFpMatch     FPIFpMatch;
+	PFPICloseDevice FPICloseDevice;
+	PFPITplFrmImgBmp  FPITplFrmImgBmp;
+};
+

+ 498 - 0
DevAdapter/nantian/FingerPrint.1.1/fingerprint.nantian.1.1.cpp

@@ -0,0 +1,498 @@
+#include "fingerprint.nantian.1.1.h"
+
+FINGERPRINTNANTIAN21_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass *&baseObj)
+{
+	baseObj = new FingerPrintNantian21();
+	if (baseObj == NULL)
+		return Error_Null;
+	else
+		return Error_Succeed;
+
+}
+FINGERPRINTNANTIAN21_API ErrorCodeEnum ReleaseDevComponent(DeviceBaseClass *&pBaseObj)
+{
+	if (pBaseObj == NULL)
+		return Error_Param;
+	FingerPrintNantian21* pTmp = (FingerPrintNantian21*)(pBaseObj);
+	delete pTmp;
+	pTmp = NULL;
+	return Error_Succeed;
+}
+// 这是已导出类的构造函数。
+// 有关类定义的信息,请参阅 FingerPrint.Nantian.4.1.h
+FingerPrintNantian21::FingerPrintNantian21()
+{
+	m_gvar = NULL;
+	m_gvar = new Gvar();
+	memset(m_errinfo.szErrMsg,0,MAX_DEV_ERROR_MSG_LEN);
+	strcpy(m_errinfo.szErrMsg,"操作成功");
+	m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+	m_ecode = Error_Succeed;
+	return;
+}
+FingerPrintNantian21::~FingerPrintNantian21()
+{
+	if (m_gvar)
+	{
+		delete m_gvar;
+		m_gvar = NULL;
+	}
+	return;
+}
+// TODO: 在此添加您的方法。
+//
+// Open Device
+// if usb device, set dwPort = 0
+ErrorCodeEnum FingerPrintNantian21::DevOpen(DWORD dwPort, DWORD dwBaudRate)
+{
+	int iret = Error_Succeed;
+	CILIXAutoTrace _at(m_gvar->m_trace,"DevOpen",&iret);
+	if (!m_gvar->m_isLoad)
+	{
+		iret = Error_DevLoadFileFailed;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"DevOpen","辅助库加载或辅助库方法加载失败");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"辅助库加载或辅助库方法加载失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	char cDevName[300]="";
+	iret = m_gvar->FPIFindDevice(m_gvar->m_port,cDevName);
+	if (iret < 0)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"DevOpen","查找设备失败,FPIFindDevice return =%d",iret);
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"查找设备失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		iret = Error_DevNotAvailable;
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	m_gvar->m_connect = TRUE;
+	iret = Error_Succeed;
+	m_ecode = (ErrorCodeEnum)iret;
+	return (ErrorCodeEnum)iret;
+}
+
+//扫描指纹并保存指纹图片到默认路径下(dep目录下)
+//计算特征值,iLength:输入代表buf最大长度,输出为特征实际长度
+//Compute features
+ErrorCodeEnum FingerPrintNantian21::Image2Feature(const char* imagePath, LPBYTE lpbFeature, int &iLength)
+{
+	int iret = Error_Succeed;
+	CILIXAutoTrace _at(m_gvar->m_trace,"Image2Feature",&iret);
+	if (!m_gvar->m_isLoad)
+	{
+		iret = Error_DevLoadFileFailed;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Feature","辅助库加载或辅助库方法加载失败");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"辅助库加载或辅助库方法加载失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	if ((strlen(imagePath)==0) || (lpbFeature == NULL))
+	{
+		iret = Error_Param;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Feature","输入参数或者输出参数为空");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"输入参数或者输出参数为空");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	if (!m_gvar->m_connect)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Feature", "设备未连接");
+		iret = Error_DevNotAvailable;
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"设备未连接");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_INFO,"Image2Feature", "传入图片路径:imagePath= %s",imagePath);
+	//录制指纹特征
+	char szBuf[1024] = "";
+	int iszlen = 0;
+	iret = m_gvar->FPIGetFeature(m_gvar->m_port,szBuf);
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_DEBUG,"Image2Feature", "FPIGetFeature return %d",iret);
+	if (iret < 0)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Feature", "录制指纹特征失败,FPIGetFeature return iret =%d",iret);
+		iret = Error_DevCommFailed;
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"录制指纹特征失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	//生成一张bmp图片
+	if (access(m_gvar->m_image,F_OK) != 0) 
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Feature", "图片路径不存在,m_gvar->m_image=%s",m_gvar->m_image);
+		iret = Error_Param;
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"图片路径不存在");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	//存储指纹图片
+	char cImageData[512*512]="";
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_DEBUG,"Image2Feature", "FPIGetImageDat  ......................");
+	iret = m_gvar->FPIGetImageDat(m_gvar->m_port, cImageData);
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_DEBUG,"Image2Feature", "FPIGetImageDat return %d",iret);
+	if (iret < 0)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Feature", "获取指纹图像数据操作失败,FPIGetImageDat return =%d",iret);
+		iret = Error_DevCommFailed;
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"获取指纹图像数据操作失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	char cPath[1024] = "";
+	strcpy(cPath,m_gvar->m_image);
+	strcat(cPath,imagePath);
+	//生成指纹图片
+	iret = m_gvar->FPISaveImage(cPath,cImageData);
+	if (iret < 0)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Feature", "保存指纹图片操作失败,FPISaveImage return =%d",iret);
+		iret = Error_DevCommFailed;
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"保存指纹图片操作失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	iszlen = 684;
+	if ((iLength < iszlen)|| (iLength == 0))
+	{	
+		iLength = iszlen;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Feature","输出指纹特征数据长度=%d",iszlen);
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"传入空间长度太小");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		iret = Error_TooSmallBuffer;
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	iLength = strlen(szBuf);
+	//新增
+	memcpy(lpbFeature,szBuf,iLength);
+	lpbFeature[iLength] = '\0';
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_DEBUG,"Image2Feature", "指纹特征数据:%s,长度:%d",szBuf,iLength);
+	iret = Error_Succeed;
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_INFO,"Image2Feature", "提取指纹特征成功");
+	m_ecode = (ErrorCodeEnum)iret;
+	return (ErrorCodeEnum)iret;
+}
+
+//生成特征模板(注册时使用)
+//Convert image to template
+ErrorCodeEnum FingerPrintNantian21::Image2Template(const char* imagePath1, const char* imagePath2, const char* imagePath3, LPBYTE lpbTemplate, int &iLength)
+{
+	int iret = Error_Succeed;
+	CILIXAutoTrace _at(m_gvar->m_trace,"Image2Template",&iret);
+	if (!m_gvar->m_isLoad)
+	{
+		iret = Error_DevLoadFileFailed;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Template","辅助库加载或辅助库方法加载失败");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"辅助库加载或辅助库方法加载失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	if (!m_gvar->m_connect)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Feature", "设备未连接");
+		iret = Error_DevNotAvailable;
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"设备未连接");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_DEBUG,"Image2Template","输入合成模板图片路径1:%s,路径2:%s,路径3:%s",
+		imagePath1,imagePath2,imagePath3);
+	if ((strlen(imagePath1)==0)||(strlen(imagePath2)==0)||(strlen(imagePath3)==0))
+	{
+		iret = Error_Param;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Template","输入合成模板图片路径为空");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"输入合成模板图片路径为空");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	if ((access(imagePath1,F_OK) != 0)||(access(imagePath2,F_OK) != 0)||(access(imagePath3,F_OK) != 0))
+	{
+		iret = Error_Param;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Template","输入合成模板图片不存在");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"输入合成模板图片不存在");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	char cMBBuf[1024] = "";
+	int iLen = 0;
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_INFO,"Image2Template","entry FPITplFrmImgBmp ...................");
+	iret = m_gvar->FPITplFrmImgBmp((char*)imagePath1,(char*)imagePath2,(char*)imagePath3,cMBBuf,&iLen);
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_INFO,"Image2Template","Exit FPITplFrmImgBmp ...................");
+	if (iret < 0)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Template","合成指纹内模板失败,FPITplFrmImgBmp return %d",iret);
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"合成指纹内模板失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		iret = Error_Hardware;
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	if ((iLength < iLen)|| (iLength == 0))
+	{	
+		iLength = iLen;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Image2Template","输出指纹特征数据长度=%d",iLen);
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"传入空间长度太小");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		iret = Error_TooSmallBuffer;
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_INFO,"Image2Template","合成指纹内模板成功,iLen = %d",iLen);
+	iLength = iLen;
+	memcpy(lpbTemplate,cMBBuf,iLength);
+	lpbTemplate[iLength] = '\0';
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_DEBUG,"Image2Template", "转base6数据:%s,长度:%d",cMBBuf,iLength);
+	iret = Error_Succeed;
+	m_ecode = (ErrorCodeEnum)iret;
+	return (ErrorCodeEnum)iret;
+}
+
+//比对校验
+//Match the feature
+ErrorCodeEnum FingerPrintNantian21::Match(LPBYTE lpbTemplate[], int iTemplateLen[] ,int templateNum, LPBYTE lbpFeature, int &iFeatureLen ,int level)
+{
+	int iret = Error_Succeed;
+	CILIXAutoTrace _at(m_gvar->m_trace,"Match",&iret);
+	if (!m_gvar->m_isLoad)
+	{
+		iret = Error_DevLoadFileFailed;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Match","辅助库加载或辅助库方法加载失败");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"辅助库加载或辅助库方法加载失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	if ((lpbTemplate == NULL)|| (lbpFeature == NULL)|| (templateNum==0))
+	{
+		iret = Error_Param;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Match","输入参数参数为空或者为0");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"输入参数参数为空");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	if (!m_gvar->m_connect)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Match", "设备未连接");
+		iret = Error_DevNotAvailable;
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"设备未连接");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_DEBUG,"Match", "指纹特征数据=%s,长度=%d",lbpFeature,iFeatureLen);
+	int i = 0;
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_INFO,"Match", "指纹比对:level=%d",level);
+	char MbData[1024] = "";
+	int ilenMb = 0;
+	char TzData[1024] = "";
+	strcpy(TzData,(char*)lbpFeature);
+	for (i=0;i<templateNum;i++)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_DEBUG,"Match", "%d指纹模板数据=%s,长度=%d",i+1,lpbTemplate[i],iTemplateLen[i]);
+		memset(MbData,0,1024);
+		//base64转二进制
+		if (iTemplateLen[i] < 684)
+		{
+			iTemplateLen[i] = 0;
+		}
+		else
+		{
+			memset(MbData,0,1024);
+			strcpy(MbData,(char*)lpbTemplate[i]);
+			iret = m_gvar->FPIFpMatch(MbData, TzData, level);
+			if (iret >= 0)//比对成功
+			{	
+				iTemplateLen[i] = 1;
+				m_gvar->m_trace->WriteTrace(CILIXTRACE_L_INFO,"Match", "指纹比对成功");
+			}
+			else
+			{
+				m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Match", "指纹比对失败,iret=%d",iret);
+				iTemplateLen[i] = 0;
+			}
+		}
+
+	}
+	iret = Error_Succeed;
+	m_ecode = (ErrorCodeEnum)iret;
+	return Error_Succeed;
+}
+
+//取消采集指纹图片
+ErrorCodeEnum FingerPrintNantian21::Cancel()
+{
+	int iret = Error_Succeed;
+	CILIXAutoTrace _at(m_gvar->m_trace,"Cancel",&iret);
+	m_gvar->m_cancel = TRUE;
+	m_ecode = (ErrorCodeEnum)iret;
+	return Error_Succeed;
+}
+//	
+//	Get category infomation about device.
+//
+ErrorCodeEnum FingerPrintNantian21::GetDevCategory(DevCategoryInfo &devCategory)
+{
+	int iret = Error_Succeed;
+	CILIXAutoTrace _at(m_gvar->m_trace, "GetDevCategory", &iret);
+	strcpy(devCategory.szType, "fingerprint");
+	strcpy(devCategory.szVendor, "nantian");
+	strcpy(devCategory.szModel, "TCM");
+	devCategory.version.wMajor = 1;
+	devCategory.version.wMinor = 0;
+	devCategory.version.wRevision = 0;
+	devCategory.version.wBuild = 4;
+	devCategory.eState = DEVICE_STATUS_NOT_READY;
+
+	if (!m_gvar->m_isLoad)
+	{
+		iret = Error_DevLoadFileFailed;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"GetDevCategory","辅助库加载或辅助库方法加载失败");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"辅助库加载或辅助库方法加载失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		devCategory.eState = DEVICE_STATUS_NOT_READY;
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum) iret;
+	}
+	if (!m_gvar->m_connect)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"GetDevCategory", "设备未连接");
+		iret = Error_DevNotAvailable;
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"设备未连接");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		devCategory.eState = DEVICE_STATUS_NOT_READY;
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum) iret;
+	}
+	//查询设备状态
+	char cDevSN[1024]="";
+	iret = m_gvar->FPIGetDevSN(m_gvar->m_port,cDevSN);
+	if (iret >= 0)
+	{
+		iret=Error_Succeed;
+		devCategory.eState = DEVICE_STATUS_NORMAL;
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	else
+	{
+		devCategory.eState = DEVICE_STATUS_FAULT;
+		iret = Error_Hardware;
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"GetDevCategory","获取不到设备信息");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"获取不到设备信息");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+}
+//	Reset device.
+//	Do the cleaning work and initialize device again in order to return to
+//	the normal condition.
+ErrorCodeEnum FingerPrintNantian21::Reset()
+{
+	int iret = Error_Succeed;
+	CILIXAutoTrace _at(m_gvar->m_trace,"Reset",&iret);
+	if (!m_gvar->m_isLoad)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Reset","动态库或动态库方法加载失败");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"动态库或动态库方法加载失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		iret = Error_DevLoadFileFailed;
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	iret = m_gvar->FPICloseDevice(m_gvar->m_port);
+	CILIX_AUX_X::Sleep(100);
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_INFO,"Reset","FPICloseDevice return %d",iret);
+	char cDevName[300]="";
+	iret = m_gvar->FPIFindDevice(m_gvar->m_port,cDevName);
+	if (iret < 0)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"Reset","设备复位失败,FPIFindDevice return %d",iret);
+		iret = Error_DevConnFailed;
+		m_gvar->m_connect = FALSE;
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"设备复位失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	m_gvar->m_trace->WriteTrace(CILIXTRACE_L_INFO,"PTR_Reset","设备复位成功");
+	m_gvar->m_connect = TRUE;
+	iret = Error_Succeed;
+	m_ecode = (ErrorCodeEnum)iret;
+	return (ErrorCodeEnum)iret;
+}
+//	
+//	Close device and do the cleaning work.
+//	ex. close connection,close port,release memery and so on
+ErrorCodeEnum FingerPrintNantian21::DevClose()
+{
+	int iret = Error_Succeed;
+	CILIXAutoTrace _at(m_gvar->m_trace,"DevClose",&iret);
+	if (!m_gvar->m_isLoad)
+	{
+		m_gvar->m_trace->WriteTrace(CILIXTRACE_L_ERROR,"DevClose","辅助库加载或辅助库方法加载失败");
+		memset(m_errinfo.szErrMsg,0,sizeof(m_errinfo.szErrMsg));
+		strcpy(m_errinfo.szErrMsg,"辅助库加载或辅助库方法加载失败");
+		m_errinfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg);
+		iret = Error_DevLoadFileFailed;
+		m_ecode = (ErrorCodeEnum)iret;
+		return (ErrorCodeEnum)iret;
+	}
+	if (m_gvar->m_connect)
+	{
+		m_gvar->FPICloseDevice(m_gvar->m_port);
+		m_gvar->m_connect = FALSE;
+	}
+	iret = Error_Succeed;
+	m_ecode = (ErrorCodeEnum)iret;
+	return (ErrorCodeEnum)iret;
+}
+//	Get last error the device issued.
+//	Error message must include explanatory memorandum ,the original error 
+//	code and anything in favour of location problem.
+ErrorCodeEnum FingerPrintNantian21::GetLastErr(DevErrorInfo &devErrInfo)
+{
+	devErrInfo.dwErrMsgLen = 0;
+	memset(devErrInfo.szErrMsg, 0, MAX_DEV_ERROR_MSG_LEN);
+	devErrInfo.dwErrMsgLen = strlen(m_errinfo.szErrMsg); 
+	memcpy(devErrInfo.szErrMsg, m_errinfo.szErrMsg, devErrInfo.dwErrMsgLen);
+	return Error_Succeed;
+}

+ 79 - 0
DevAdapter/nantian/FingerPrint.1.1/fingerprint.nantian.1.1.h

@@ -0,0 +1,79 @@
+// 下列 ifdef 块是创建使从 DLL 导出更简单的
+// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 FINGERPRINTNANTIAN41_EXPORTS
+// 符号编译的。在使用此 DLL 的
+// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
+// FINGERPRINTNANTIAN41_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
+// 符号视为是被导出的。
+
+
+#include "../../include/FingerPrintClass.h"
+#include "Gvar.h"
+
+// 此类是从 FingerPrint.Nantian.4.1.dll 导出的
+class FingerPrintNantian21 : public FingerPrintClass
+{
+public:
+	FingerPrintNantian21();
+	~FingerPrintNantian21();
+	// TODO: 在此添加您的方法。
+	//
+	// Open Device
+	// if usb device, set dwPort = 0
+	virtual ErrorCodeEnum DevOpen(DWORD dwPort, DWORD dwBaudRate);
+
+	//扫描指纹并保存指纹图片到默认路径下(dep目录下)
+	//计算特征值,iLength:输入代表buf最大长度,输出为特征实际长度
+	//Compute features
+	virtual ErrorCodeEnum Image2Feature(const char* imagePath, LPBYTE lpbFeature, int &iLength);
+
+	//生成特征模板(注册时使用)
+	//Convert image to template
+	virtual ErrorCodeEnum Image2Template(const char* imagePath1, const char* imagePath2, const char* imagePath3, LPBYTE lpbTemplate, int &iLength);
+
+	//比对校验
+	//Match the feature
+	virtual ErrorCodeEnum Match(LPBYTE lpbTemplate[], int iTemplateLen[] ,int templateNum, LPBYTE lbpFeature, int &iFeatureLen ,int level);
+
+	//取消采集指纹图片
+	virtual ErrorCodeEnum Cancel();
+	//	
+	//	Get category infomation about device.
+	//
+	virtual ErrorCodeEnum GetDevCategory(DevCategoryInfo &devCategory);
+	//	Reset device.
+	//	Do the cleaning work and initialize device again in order to return to
+	//	the normal condition.
+	virtual ErrorCodeEnum Reset();
+	//	
+	//	Close device and do the cleaning work.
+	//	ex. close connection,close port,release memery and so on
+	virtual ErrorCodeEnum DevClose();
+	//	Get last error the device issued.
+	//	Error message must include explanatory memorandum ,the original error 
+	//	code and anything in favour of location problem.
+	virtual ErrorCodeEnum GetLastErr(DevErrorInfo &devErrInfo);
+
+private:
+	Gvar *m_gvar;
+	DevErrorInfo m_errinfo;
+	unsigned char pRawData[512*512+1];
+	unsigned char pBmpData[512*512+1];
+	char ErrInfo[500];
+	ErrorCodeEnum m_ecode;
+	DWORD m_mode;
+};
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#pragma pack(push, 1)
+
+#define FINGERPRINTNANTIAN21_API __attribute__((visibility("default")))
+FINGERPRINTNANTIAN21_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass *&baseObj);
+FINGERPRINTNANTIAN21_API ErrorCodeEnum ReleaseDevComponent(DeviceBaseClass *&pBaseObj);
+#pragma pack(pop)
+
+#ifdef __cplusplus
+}
+#endif

+ 13 - 0
DevAdapter/nantian/cardissuer.1.1/CMakeLists.txt

@@ -0,0 +1,13 @@
+rvc_dev_define_module("CardIssuer")
+set(${MODULE_PREFIX}_VENDOR "nantian")
+set(${MODULE_PREFIX}_VERSION "1")
+set(${MODULE_PREFIX}_BATCH "1")
+
+set(${MODULE_PREFIX}_SRCS SHARED
+        cardissuer.nantian.1.1.cpp
+        )
+
+
+rvc_dev_config_library(${MODULE_NAME} ${MODULE_PREFIX})
+
+rvc_dev_target_install(${MODULE_FULL_NAME})

+ 1203 - 0
DevAdapter/nantian/cardissuer.1.1/cardissuer.nantian.1.1.cpp

@@ -0,0 +1,1203 @@
+#include "cardissuer.nantian.1.1.h"
+#include<cstring>
+#include <cstdio>
+CardIssuerClassImpl::CardIssuerClassImpl()
+        :m_mode(0)
+{
+	dplHandle = NULL;
+	DRVCardDispenser = NULL;
+	m_isDevOpened = false;
+	m_isCanceled = false;
+
+	m_busy_flag = false;
+	m_signal_get_flag = false;
+
+	m_SetCardInTypeFlag = 0;
+	m_CardInTypeFlag = false;
+
+	RetainBox = 0;
+
+	m_trace = NULL;
+	m_trace = new CILIXTrace(NULL,"CardIssuer","CardIssuer_ACT_F55570");
+	
+	if(!LoadNTDRVDLL()) return ;
+}
+
+CardIssuerClassImpl::~CardIssuerClassImpl()
+{
+	if (DRVCardDispenser != NULL) Destroy_DRV_CardDispenser(DRVCardDispenser);
+	if (dplHandle)
+        dlclose(dplHandle);
+	DRVCardDispenser = NULL;
+	dplHandle = NULL;
+}
+
+bool CardIssuerClassImpl::LoadNTDRVDLL()
+{
+	char szInIPath[1024],szNTDRVPath[1024];
+
+	CILIX_AUX_X::CILIX_GetModuleCurPath(szInIPath);
+	sprintf(szNTDRVPath,"%s%s",szInIPath,"libdrv_act_f55570.nantian.so");
+	dplHandle = NULL;
+    void *pszErr = NULL;
+	
+	
+    dplHandle = dlopen(szNTDRVPath, RTLD_LAZY);
+    if (!dplHandle || pszErr)
+    {
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadNTDRVDLL","加载底层库%s失败",szNTDRVPath);
+        return FALSE;
+    }
+	Create_DRV_CardDispenser = NULL;
+	Create_DRV_CardDispenser = (pCreate_DRV_CardDispenser)dlsym(dplHandle,"Create_DRV_CardDispenser");
+	if(Create_DRV_CardDispenser == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadNTDRVDLL","加载底层库方法 Create_DRV_CardDispenser 失败",szNTDRVPath);
+		return false;
+	}
+	Destroy_DRV_CardDispenser = NULL;
+	Destroy_DRV_CardDispenser = (pDestroy_DRV_CardDispenser)dlsym(dplHandle,"Destroy_DRV_CardDispenser");
+	if(Destroy_DRV_CardDispenser == NULL)
+	{
+		m_trace->WriteTrace(CILIXTRACE_L_ERROR,"LoadNTDRVDLL","加载底层库方法 Destroy_DRV_CardDispenser 失败",szNTDRVPath);
+		return false;
+	}
+
+	DRVCardDispenser = Create_DRV_CardDispenser();
+	return true;
+}
+
+
+ErrorCodeEnum CardIssuerClassImpl::GetDevCategory(DevCategoryInfo &devCategory)
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+	
+    ErrorCodeEnum err = Error_Succeed;
+    std::strcpy(devCategory.szModel, "ACT_F55570");
+    std::strcpy(devCategory.szType, "CardIssuer");
+    std::strcpy(devCategory.szVendor, "nantian");
+	
+	m_busy_flag = false;
+    return err;
+}
+
+ErrorCodeEnum CardIssuerClassImpl::Reset()
+{
+   m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = 0;
+	try
+	{
+		if(!m_isDevOpened) 
+		{
+			strcpy(m_errorInfo.szErrMsg, "device not connect");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet =Error_DevConnFailed;
+			throw(iRet);
+		}
+		//复位设备
+		char *sReset[10] = {NULL};
+		char PowerOnFlag[10] ="1";
+		char PowerOffFlag[10]="3";
+		sReset[1] = PowerOnFlag;
+		sReset[2] = PowerOffFlag;
+		iRet = DRVCardDispenser->ResetDev(3,sReset);
+		if(iRet != 0)
+		{
+			strcpy(m_errorInfo.szErrMsg, "hardware error");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet = Error_Hardware;
+			throw(iRet);
+		}
+		iRet = Error_Succeed;
+	}
+	catch(int eret){iRet = eret;}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+
+ErrorCodeEnum CardIssuerClassImpl::DevClose()
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = 0;
+	iRet = DRVCardDispenser->CloseDev();
+	if(iRet != 0)
+	{
+		m_isDevOpened = false;
+
+		iRet =Error_DevConnFailed;
+	}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+
+ErrorCodeEnum CardIssuerClassImpl::GetLastErr(DevErrorInfo &devErrInfo)
+{
+    static int times = 0;
+    char szMessage[128];
+    sprintf(szMessage, "this is the %d times error message", ++times);
+    strcpy(devErrInfo.szErrMsg, szMessage);
+    devErrInfo.dwErrMsgLen = strlen(szMessage);
+    return Error_Succeed;
+}
+
+DEVICEBASE_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass *&baseObj)
+{
+    baseObj = new CardIssuerClassImpl();
+    if(baseObj == NULL) {
+    return Error_Resource;
+    } else {
+    return Error_Succeed;
+    }
+}
+DEVICEBASE_API ErrorCodeEnum  ReleaseDevComponent(DeviceBaseClass *&pBaseObj)
+{
+    if(pBaseObj == NULL) {
+    return Error_Param;
+    }
+    if(CardIssuerClassImpl* pTmp = dynamic_cast<CardIssuerClassImpl*>(pBaseObj))
+    {
+    delete pTmp;
+    pTmp = NULL;
+    return Error_Succeed;
+    }
+    return Error_Param;
+}
+
+ErrorCodeEnum CardIssuerClassImpl::DevOpen(DWORD dwPort, DWORD dwBaudRate)
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = Error_Succeed;
+	char *CapInfo[10];
+	for (int i = 0; i < 10; i++)
+	{
+		CapInfo[i] = new char[20];
+		memset(CapInfo[i], 0, 20);
+	}
+	try
+	{
+		char szComPort[100];
+		memset(szComPort,0,sizeof(szComPort));
+		sprintf(szComPort,"Com%d",(int)dwPort);
+
+		memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+		iRet = DRVCardDispenser->OpenDev(szComPort,(int)dwBaudRate);
+		if(iRet != 0)
+		{
+			strcpy(m_errorInfo.szErrMsg, "connect to device failed");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			m_isDevOpened = false;
+
+			iRet =Error_DevConnFailed;
+			throw(iRet);
+		}
+		m_isDevOpened = true ;
+
+		char szErrorMsg[1024] = "";
+
+		//复位设备
+		char *sReset[10] = {NULL};
+		char PowerOnFlag[10] ="1";
+		char PowerOffFlag[10]="3";
+		sReset[1] = PowerOnFlag;
+		sReset[2] = PowerOffFlag;
+		iRet = DRVCardDispenser->ResetDev(3,sReset);
+		if(iRet != 0)
+		{
+			strcpy(m_errorInfo.szErrMsg, "hardware error");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet = Error_Hardware;
+			throw(iRet);
+		}
+
+		int mSupplyBin =2, mRetainBin =1, mHoldBin =0;
+
+		DRVCardDispenser->GetDevCap(CapInfo);
+		mSupplyBin = atoi(CapInfo[0]);
+		mRetainBin = atoi(CapInfo[1]);
+		mHoldBin = atoi(CapInfo[2]);
+		iRet = Error_Succeed;
+	}catch(int eret){iRet = eret;}
+
+	m_busy_flag = false;
+	for (int i = 0; i < 10; i++)
+	{
+		delete[]CapInfo[i];
+	}
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::GetDevStatus(CardIssuerStatus &devStatus)
+{
+	{
+
+		if (m_busy_flag == true || m_signal_get_flag == true)
+		{
+			if (m_StatusErrorCode == Error_Succeed)
+				devStatus = tempStatus;
+
+			return m_StatusErrorCode;
+		}
+	}
+
+	m_signal_get_flag = true;
+
+	int iRet = Error_Succeed;
+	memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+	char *BoxStatus[200]={NULL};
+	for (int i = 0; i < 200; i++)
+	{
+		BoxStatus[i] = new char[20];
+		memset(BoxStatus[i], 0, 20);
+	}
+	try
+	{
+		if(!m_isDevOpened) 
+		{
+			strcpy(m_errorInfo.szErrMsg, "device not connect");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet =Error_DevConnFailed;
+			throw(iRet);
+		}
+
+		//***设备状态查询
+		char sDevice[10] = "";
+		char sMedia[10] = "";
+		char sChipPower[10] = "";
+		char sRetainCount[10] = "";
+		char sShutter[10] = "";
+		char *sStatus[100] = {NULL};
+		sStatus[1] = sDevice;
+		sStatus[2] = sMedia;
+		sStatus[4] = sChipPower;
+		sStatus[8] = sRetainCount;
+		sStatus[16] = sShutter;
+		DRVCardDispenser->GetDevStatus(0,sStatus);
+
+		//***判断设备状态
+		if ((atoi(sDevice) != CARDDISPENSER_DEVONLINE) && ((atoi(sDevice) != CARDDISPENSER_DEVBUSY)))
+		{
+			strcpy(m_errorInfo.szErrMsg, "hardware error");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet = Error_Hardware;
+			throw(iRet);
+		}
+		switch((atoi(sMedia)))
+		{
+		case CARDDISPENSER_MEDIAPRESENT:
+			{
+				tempStatus.eMedia = CI_MEDIA_PRESENT;
+				if ((atoi(sChipPower)) == CARDDISPENSER_CHIPONLINE || (atoi(sChipPower)) == CARDDISPENSER_CHIPBUSY)
+					tempStatus.eMedia = CI_MEDIA_IC;
+			}break;
+		case CARDDISPENSER_MEDIANOTPRESENT:
+			{
+				tempStatus.eMedia = CI_MEDIA_NOTPRESENT;								   
+			}break;
+		case CARDDISPENSER_MEDIAJAMMED:tempStatus.eMedia = CI_MEDIA_JAMMED;break;
+		case CARDDISPENSER_MEDIAENTERING:
+			{
+				tempStatus.eMedia = CI_MEDIA_ENTERING;								   
+			}break;
+		case CARDDISPENSER_MEDIALATCHED:
+			{
+				tempStatus.eMedia = CI_MEDIA_IC;							   
+			}break;
+		default:
+			{
+				tempStatus.eMedia = CI_MEDIA_NOTPRESENT;								   
+			}break;
+		}
+		
+		//吞卡数
+		tempStatus.dwRetainCount = atoi(sChipPower) ;
+
+		int ierr = DRVCardDispenser->GetCardBoxStatus(BoxStatus);
+
+		//回收箱状态
+		switch (atoi(BoxStatus[101]))
+		{
+		case CARDDISPENSER_BOXSTATUSOK:
+		case CARDDISPENSER_BOXSTATUSLOW:
+		case CARDDISPENSER_BOXSTATUSEMPTY:
+		case CARDDISPENSER_BOXSTATUSHIGH:
+			RetainBox = 0;
+			tempStatus.eRetainBin = CI_RETAINBIN_OK;
+			break;
+		case CARDDISPENSER_BOXSTATUSFULL:
+			tempStatus.eRetainBin = CI_RETAINBIN_FULL;
+			RetainBox = 1;
+			break;
+		case CARDDISPENSER_BOXSTATUSMISSING:
+		case CARDDISPENSER_BOXSTATUSINOP:
+		case CARDDISPENSER_BOXSTATUSUNKNOWN:
+			tempStatus.eRetainBin = CI_RETAIN_NOTSUPP;
+			RetainBox = 2;
+			break;
+		default:
+			tempStatus.eRetainBin = CI_RETAIN_NOTSUPP;
+			RetainBox = 2;
+			break;
+		}
+		//发卡箱状态
+		for (int i = 1; i <= 2; i++)
+		{
+			switch (atoi(BoxStatus[i]))
+			{
+			case CARDDISPENSER_BOXSTATUSOK:
+			case CARDDISPENSER_BOXSTATUSFULL:
+			case CARDDISPENSER_BOXSTATUSHIGH:
+				tempStatus.eIssuerBin[i-1] = CI_ISSUEHOPPER_OK;
+				break;
+			case CARDDISPENSER_BOXSTATUSLOW:
+				tempStatus.eIssuerBin[i-1] = CI_ISSUEHOPPER_LOW;
+				break;
+			case CARDDISPENSER_BOXSTATUSEMPTY:
+				tempStatus.eIssuerBin[i-1] = CI_ISSUEHOPPER_EMPTY;
+				break;
+			case CARDDISPENSER_BOXSTATUSMISSING:
+			case CARDDISPENSER_BOXSTATUSINOP:
+			case CARDDISPENSER_BOXSTATUSUNKNOWN:
+				tempStatus.eIssuerBin[i-1] = CI_ISSUEHOPPER_NOTSUPP;
+				break;
+			default:
+				tempStatus.eIssuerBin[i-1] = CI_ISSUEHOPPER_NOTSUPP;
+				break;
+			}
+		}
+		//发卡箱3状态
+		tempStatus.eIssuerBin[2] = CI_ISSUEHOPPER_NOTSUPP;
+
+		tempStatus.dwIssuerCount[0] = 0;
+		tempStatus.dwIssuerCount[1] = 0;
+		tempStatus.dwIssuerCount[2] = 0;
+
+	}catch(int eret)
+	{
+		iRet = eret;
+	}
+	devStatus = tempStatus;
+	m_signal_get_flag = false;
+	m_StatusErrorCode = (ErrorCodeEnum)iRet;
+	for (int i = 0; i < 200; i++)
+	{
+		delete[]BoxStatus[i];
+	}
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::GetDeviceSN(char *&pDevSN)
+{
+	int iRet = Error_Succeed;
+	strcpy(pDevSN, "");
+	return (ErrorCodeEnum)iRet;
+}
+//发卡机通用接口
+ErrorCodeEnum CardIssuerClassImpl::MoveCard(CardPosEnum eCardPos, int hopperNo )
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = Error_Succeed ;
+	try
+	{
+		if(!m_isDevOpened) 
+		{
+			strcpy(m_errorInfo.szErrMsg, "device not connect");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet =Error_DevConnFailed;
+			throw(iRet);
+		}
+
+		memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+
+		//***设备状态查询
+		char sDevice[10] = "";
+		char sMedia[10] = "";
+		char sChipPower[10] = "";
+		char sRetainCount[10] = "";
+		char sShutter[10] = "";
+		char *sStatus[100] = {NULL};
+		sStatus[1] = sDevice;
+		sStatus[2] = sMedia;
+		sStatus[4] = sChipPower;
+		sStatus[8] = sRetainCount;
+		sStatus[16] = sShutter;
+		DRVCardDispenser->GetDevStatus(0,sStatus);
+		if(stoi(sDevice) != CARDDISPENSER_DEVONLINE)
+		{
+			strcpy(m_errorInfo.szErrMsg, "hardware error");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet =Error_Hardware;
+			throw(iRet);		
+		}
+		
+		m_trace->WriteTrace(CILIXTRACE_L_INFO,"MoveCard","eCardPos:%d",eCardPos);
+		switch(eCardPos)
+		{
+			//退卡
+		case CI_MOVECARD_FRONT_GATE:
+			{
+				if(atoi(sMedia) == CARDDISPENSER_MEDIANOTPRESENT)
+				{
+					strcpy(m_errorInfo.szErrMsg, "device not card to Gate");
+					m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+					iRet =Error_Param;
+					throw(iRet);
+				}
+				if((atoi(sMedia)==CARDDISPENSER_MEDIALATCHED)||
+					(atoi(sChipPower) == CARDDISPENSER_CHIPONLINE)||
+					(atoi(sChipPower) == CARDDISPENSER_CHIPBUSY))
+				{
+					iRet = DRVCardDispenser->ICCPower(12,NULL,NULL);
+					if(iRet != 0)
+					{
+						strcpy(m_errorInfo.szErrMsg, "device ReleaseDactivates Fail!");
+						m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+						iRet =Error_Hardware;
+						throw(iRet);
+					}
+				}
+				iRet = DRVCardDispenser->EjectCard();
+				if(iRet != 0)
+				{
+					strcpy(m_errorInfo.szErrMsg, "device EjectCard Fail!");
+					m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+					iRet =Error_Hardware;
+					throw(iRet);
+				}
+				m_SetCardInTypeFlag = 0;
+				m_CardInTypeFlag= false;
+			}
+			break;
+			//吞卡
+		case CI_MOVECARD_BACK_NOT_HOLD:
+			{
+				if(RetainBox != 0)
+				{
+					iRet =Error_Hardware;
+					throw(iRet);
+				}
+				if(atoi(sMedia) == CARDDISPENSER_MEDIANOTPRESENT)
+				{
+					strcpy(m_errorInfo.szErrMsg, "device not card to BACK_NOT_HOLD");
+					m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+					iRet =Error_Param;
+					throw(iRet);
+				}
+				if((atoi(sMedia)==CARDDISPENSER_MEDIALATCHED)||
+					(atoi(sChipPower) == CARDDISPENSER_CHIPONLINE)||
+					(atoi(sChipPower) == CARDDISPENSER_CHIPBUSY))
+				{
+					iRet = DRVCardDispenser->ICCPower(12,NULL,NULL);
+					if(iRet != 0)
+					{
+						strcpy(m_errorInfo.szErrMsg, "device ReleaseDactivates Fail!");
+						m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+						iRet =Error_Hardware;
+						throw(iRet);
+					}
+				}
+				int tryTime = 0;
+STARTRETAIN:
+				iRet = DRVCardDispenser->RetainCard(101);
+				if(iRet != 0)
+				{
+					if((iRet == E_CARDDISPENSER_RETIANBINFULL) && (tryTime <= 1))
+					{
+						iRet = DRVCardDispenser->SetRetainCount(0);
+						tryTime++;
+						goto STARTRETAIN;	
+					}
+					m_trace->WriteTrace(CILIXTRACE_L_INFO,"MoveCard","CI_MOVECARD_BACK_NOT_HOLD.tryTime:%d",tryTime);
+					strcpy(m_errorInfo.szErrMsg, "device RetainCard Fail!");
+					m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+					iRet =Error_Hardware;
+					throw(iRet);
+				}
+				m_SetCardInTypeFlag = 0;
+				m_CardInTypeFlag= false;
+			}
+			break;
+			//发卡
+		case CI_MOVECARD_FROM_HOPPER:
+			{
+				if(atoi(sMedia) != CARDDISPENSER_MEDIANOTPRESENT)
+				{
+					strcpy(m_errorInfo.szErrMsg, "device not card not FROM_HOPPER");
+					m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+					iRet =Error_Param;
+					throw(iRet);
+				}
+				iRet = DRVCardDispenser->Dispense(hopperNo);
+				if(iRet != 0)
+				{
+					strcpy(m_errorInfo.szErrMsg, "device dispenser card error");
+					m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+					iRet =Error_Hardware;
+					throw(iRet);
+				}
+			}
+			break;
+
+		}
+	}
+	catch(int eret)
+	{
+		iRet = eret;
+	}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SetCardInType(CardInEnum eCardIn)
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	if(m_SetCardInTypeFlag != 0)
+	{
+		while(m_SetCardInTypeFlag != 2) 
+		{;}
+	}
+
+	m_SetCardInTypeFlag = 1;
+
+	int iRet = Error_Succeed;
+	try
+	{
+
+		int iInsertAction = 0;
+		switch(eCardIn)
+		{
+		case CI_CARD_IN_TYPE_FORBIDDEN:{iInsertAction= 0; m_CardInTypeFlag = false;}break;
+		case CI_CARD_IN_TYPE_MAG:      {iInsertAction= 3;}break;
+		case CI_CARD_IN_TYPE_ALL:      {iInsertAction= 1;}break;
+		}
+
+		if(m_CardInTypeFlag)
+			throw 0;
+
+		iRet = DRVCardDispenser->InsertCard(iInsertAction);
+		if(iRet != 0)
+		{
+			strcpy(m_errorInfo.szErrMsg, "hardware error");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet = Error_Hardware;
+			throw(iRet);
+		}
+		if(eCardIn!=CI_CARD_IN_TYPE_FORBIDDEN)
+			m_CardInTypeFlag = true;
+
+		iRet = Error_Succeed;
+	}
+	catch(int eret)
+	{
+		iRet = eret;
+	}
+	m_busy_flag = false;
+	m_SetCardInTypeFlag = 2;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::MagRead(MagTracks &magTracks)
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = Error_Succeed;
+	try
+	{
+		memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+
+		char magTrack1[1024]="";
+		char magTrack2[1024]="";
+		char magTrack3[1024]="";
+		char *magList[10]={NULL};
+		magList[1] = magTrack1;
+		magList[2] = magTrack2;
+		magList[4] = magTrack3;
+
+		int magTrackStatus[10]={0};
+		m_trace->WriteTrace(CILIXTRACE_L_INFO,"MagRead","magTracks.eRange:%d",magTracks.eRange);
+		iRet = DRVCardDispenser->ReadTrack(magTracks.eRange,magList,magTrackStatus);
+
+		if ((magTracks.eRange&CI_TRACK_RANGE_1) == CI_TRACK_RANGE_1)
+		{
+			magTracks.track[CI_TRACK_SOURCE_1].eSource = CI_TRACK_SOURCE_1;
+			if ((iRet==E_DRVBASE_SUCCESS)&&(magTrackStatus[1] == E_DRVBASE_SUCCESS))
+			{
+				magTracks.track[CI_TRACK_SOURCE_1].eStatus = CI_DATA_OK;
+				magTracks.track[CI_TRACK_SOURCE_1].dwSize = strlen(magTrack1);
+				memcpy(magTracks.track[CI_TRACK_SOURCE_1].data, magTrack1, magTracks.track[CI_TRACK_SOURCE_1].dwSize);
+				magTracks.track[CI_TRACK_SOURCE_1].data[magTracks.track[CI_TRACK_SOURCE_1].dwSize] = '\0';
+			}
+			else
+			{
+				magTracks.track[CI_TRACK_SOURCE_1].eStatus = CI_DATA_INVALID;
+				magTracks.track[CI_TRACK_SOURCE_1].dwSize = 0;
+				magTracks.track[CI_TRACK_SOURCE_1].data[magTracks.track[CI_TRACK_SOURCE_1].dwSize] = '\0';	
+			}
+		}
+		//Track2
+		if ((magTracks.eRange&CI_TRACK_RANGE_2) == CI_TRACK_RANGE_2)
+		{
+			magTracks.track[CI_TRACK_SOURCE_2].eSource = CI_TRACK_SOURCE_2;
+			if ((iRet==E_DRVBASE_SUCCESS)&&(magTrackStatus[2] == E_DRVBASE_SUCCESS))
+			{	
+				magTracks.track[CI_TRACK_SOURCE_2].eStatus = CI_DATA_OK;
+				magTracks.track[CI_TRACK_SOURCE_2].dwSize = strlen(magTrack2);
+				memcpy(magTracks.track[CI_TRACK_SOURCE_2].data, magTrack2, magTracks.track[CI_TRACK_SOURCE_2].dwSize);
+				magTracks.track[CI_TRACK_SOURCE_2].data[magTracks.track[CI_TRACK_SOURCE_2].dwSize] = '\0';
+			}
+			else
+			{
+				magTracks.track[CI_TRACK_SOURCE_2].eStatus = CI_DATA_INVALID;
+				magTracks.track[CI_TRACK_SOURCE_2].dwSize = 0;
+				magTracks.track[CI_TRACK_SOURCE_2].data[magTracks.track[CI_TRACK_SOURCE_2].dwSize] = '\0';			
+			}
+		}
+
+		//Track3
+		if ((magTracks.eRange&CI_TRACK_RANGE_3) == CI_TRACK_RANGE_3)
+		{
+			magTracks.track[CI_TRACK_SOURCE_3].eSource = CI_TRACK_SOURCE_3;
+			if ((iRet==E_DRVBASE_SUCCESS)&&(magTrackStatus[4] == E_DRVBASE_SUCCESS))
+			{	
+				magTracks.track[CI_TRACK_SOURCE_3].eStatus = CI_DATA_OK;
+				magTracks.track[CI_TRACK_SOURCE_3].dwSize = strlen(magTrack3);
+				memcpy(magTracks.track[CI_TRACK_SOURCE_3].data, magTrack3, magTracks.track[CI_TRACK_SOURCE_3].dwSize);
+				magTracks.track[CI_TRACK_SOURCE_3].data[magTracks.track[CI_TRACK_SOURCE_3].dwSize] = '\0';
+			}
+			else
+			{
+				magTracks.track[CI_TRACK_SOURCE_3].eStatus = CI_DATA_INVALID;
+				magTracks.track[CI_TRACK_SOURCE_3].dwSize = 0;
+				magTracks.track[CI_TRACK_SOURCE_3].data[magTracks.track[CI_TRACK_SOURCE_3].dwSize] = '\0';
+			}
+		}
+
+	}
+	catch(int eret)
+	{
+		iRet = eret;
+	}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::MagWrite(MagTracks magTracks, MagWriteModeEnum eWriteMode)
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = Error_Succeed;
+	memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+
+	int ierr = 0;
+	BOOL write_success_flag = FALSE;
+
+	char magTrack1[1024]="";
+	char magTrack2[1024]="";
+	char magTrack3[1024]="";
+	char *magList[10]={NULL};
+	magList[1] = magTrack1;
+	magList[2] = magTrack2;
+	magList[4] = magTrack3;
+
+	int magTrackStatus[10]={0};
+	//磁道解析
+	//Track1
+	if ((magTracks.eRange&CI_TRACK_RANGE_1) == CI_TRACK_RANGE_1)
+	{
+		if (magTracks.track[CI_TRACK_SOURCE_1].dwSize != 0)
+		{
+			memset(magTrack1,0,sizeof(magTrack1));
+			memcpy(magTrack1,magTracks.track[CI_TRACK_SOURCE_1].data,strlen((char *)magTracks.track[CI_TRACK_SOURCE_1].data));
+			ierr = DRVCardDispenser->WriteTrack(CI_TRACK_RANGE_1,magList,magTrackStatus);
+			if ((ierr == E_DRVBASE_SUCCESS)&&(magTrackStatus[1] == E_DRVBASE_SUCCESS))
+			{
+				write_success_flag = TRUE;
+			}
+		}
+	}
+
+	//Track2
+	if ((magTracks.eRange&CI_TRACK_RANGE_2) == CI_TRACK_RANGE_2)
+	{
+		if (magTracks.track[CI_TRACK_SOURCE_2].dwSize != 0)
+		{
+			memset(magTrack2,0,sizeof(magTrack2));
+			memcpy(magTrack2,magTracks.track[CI_TRACK_SOURCE_2].data,strlen((char *)magTracks.track[CI_TRACK_SOURCE_2].data));
+			ierr = DRVCardDispenser->WriteTrack(CI_TRACK_RANGE_2,magList,magTrackStatus);
+			if ((ierr == E_DRVBASE_SUCCESS)&&(magTrackStatus[2] == E_DRVBASE_SUCCESS))
+			{
+				write_success_flag = TRUE;
+			}
+		}
+	}
+
+	//Track3
+	if ((magTracks.eRange&CI_TRACK_RANGE_3) == CI_TRACK_RANGE_3)
+	{
+		if (magTracks.track[CI_TRACK_SOURCE_3].dwSize != 0)
+		{
+			memset(magTrack3,0,sizeof(magTrack3));
+			memcpy(magTrack3,magTracks.track[CI_TRACK_SOURCE_3].data,strlen((char *)magTracks.track[CI_TRACK_SOURCE_3].data));
+			ierr = DRVCardDispenser->WriteTrack(CI_TRACK_RANGE_3,magList,magTrackStatus);
+			if ((ierr == E_DRVBASE_SUCCESS)&&(magTrackStatus[4] == E_DRVBASE_SUCCESS))
+			{
+				write_success_flag = TRUE;
+			}
+		}
+	}
+
+	if (write_success_flag == FALSE)
+	{
+		strcpy(m_errorInfo.szErrMsg, "hardware error");
+		m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+		iRet = Error_Hardware;
+	}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SetRetractCounter(DWORD dwCount)
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = Error_Succeed;
+
+	memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+
+	int ierr = 0;
+
+	//清空回收箱计数
+	if (dwCount == 0)
+	{
+		ierr = DRVCardDispenser->SetRetainCount(0);
+
+		if (ierr < 0)
+		{
+			strcpy(m_errorInfo.szErrMsg, "hardware error");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet = Error_Hardware;
+		}
+	}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SetIssuerCounter(DWORD dwCount, int hopperNo )
+{
+	int iRet = 0 ;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::ActiveICCard()
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = Error_Succeed;
+
+	memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+
+	unsigned char sATR[1024] = "";
+	int iATR = 0;
+
+	int ierr = 0;
+	iRet = DRVCardDispenser->ICCPower(2, (char*)sATR, &iATR);
+
+	if (iRet < 0)
+	{
+		strcpy(m_errorInfo.szErrMsg, "hardware error");
+		m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+		iRet = Error_Hardware;
+	}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::ContactIC()
+{
+
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = 0;
+
+	memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+
+	unsigned char sATR[1024] = "";
+	int iATR = 0;
+	int ierr = 0;
+
+	iRet = DRVCardDispenser->ICCPower(1, (char*)sATR, &iATR);
+
+	if (iRet  < 0)
+	{
+		strcpy(m_errorInfo.szErrMsg, "hardware error");
+		m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+		iRet = Error_Hardware;
+	}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::ReleaseIC()
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = 0;
+
+	memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+
+	iRet = DRVCardDispenser->ICCPower(4, NULL, NULL);
+
+	if (iRet < 0)
+	{
+		strcpy(m_errorInfo.szErrMsg, "hardware error");
+		m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+		iRet = Error_Hardware;
+	}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::WarmReset()
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = 0;
+	
+	memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+
+	unsigned char sATR[1024] = "";
+	int iATR = 0;
+	char sErrMsg[100] = "";
+
+	iRet = DRVCardDispenser->ICCPower(12, NULL, NULL);
+
+	iRet = DRVCardDispenser->ICCPower(3, (char*)sATR, &iATR);
+
+	if (iRet < 0)
+	{
+		strcpy(m_errorInfo.szErrMsg, "hardware error");
+		m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+		iRet = Error_Hardware;
+	}
+	m_busy_flag = false;
+
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::ICCommand(CmdInfo sendBuf, CmdInfo &recvBuf)
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = 0;
+
+	try
+	{
+		memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+
+		unsigned char szSendData[1024] = "";
+		memset(szSendData,0,sizeof(szSendData));
+		int iSendLength = 0;
+		memcpy(szSendData,sendBuf.data,sendBuf.dwSize);
+		iSendLength = sendBuf.dwSize;
+		unsigned char szRecvData[1024] = "";
+		int iRecvLength = 0;
+TRANSMIT:
+
+		memset(szRecvData,0,sizeof(szRecvData));
+		iRet = DRVCardDispenser->ICCTransmit(0, (char*)szSendData, iSendLength, (char*)szRecvData, &iRecvLength);
+
+		if (iRet < 0)
+		{
+			strcpy(m_errorInfo.szErrMsg, "hardware error");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet = Error_Hardware;
+			throw(iRet);
+		}
+		if (szRecvData[iRecvLength-2] == 0x61)
+		{
+			memset(szSendData,0,sizeof(szSendData));
+			szSendData[0]=0x00;
+			szSendData[1]=0xC0;
+			szSendData[2]=0x00;
+			szSendData[3]=0x00;	 
+			szSendData[4]=szRecvData[iRecvLength-1];
+			iSendLength=5;
+			goto  TRANSMIT;
+		}
+		else if (szRecvData[iRecvLength-2] == 0x6C)
+		{
+			szSendData[iSendLength-1]=szRecvData[iRecvLength-1];
+			goto  TRANSMIT;
+		}
+		memcpy(recvBuf.data,szRecvData,iRecvLength);
+		recvBuf.dwSize = iRecvLength;
+
+	}catch(int eret){iRet = eret;}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::DeactivateICCard()
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = Error_Succeed;
+
+	memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+
+	char sErrMsg[100] = "";
+
+	iRet = DRVCardDispenser->ICCPower(8, NULL, NULL);
+
+	if (iRet < 0)
+	{
+		strcpy(m_errorInfo.szErrMsg, "hardware error");
+		m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+		iRet = Error_Hardware;
+	}
+	m_busy_flag = false;
+	return (ErrorCodeEnum)iRet;
+}
+
+//非接部分
+ErrorCodeEnum CardIssuerClassImpl::ActiveContactlessICCard(char fstType, char scdType, char thdType, char &outType)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::DeactContactlessICCard()
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::MifareCommand(MifareFuctionEnum eFunType, CmdInfo sendBuf, CmdInfo &recvBuf)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::RFTypeABCommand(CmdInfo sendBuf, CmdInfo &recvBuf)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+
+///以下是便携式卡机特有API,接口实现中其他机型直接返回Error_NotImpl即可//
+/////////////////////////////////////////////////////////////////////////
+ErrorCodeEnum CardIssuerClassImpl::DevOpenEx(DWORD dwPort, DWORD dwBaudRate, BYTE btOpenType, const char *pDevSN, BYTE &btType)
+{
+	m_busy_flag = true;
+	WAITING_LOOP();
+
+	int iRet = Error_Succeed;
+	char *CapInfo[10];
+	for (int i = 0; i < 10; i++)
+	{
+		CapInfo[i] = new char[20];
+		memset(CapInfo[i], 0, 20);
+	}
+	try
+	{
+		int iBaud = 38400;
+		char szComPort[100];
+		memset(szComPort,0,sizeof(szComPort));
+
+		if(dwPort<0)strcpy(szComPort,"/dev/ttyXRUSB1");
+		else sprintf(szComPort,"/dev/ttyXRUSB%d",dwPort - 1);
+		
+		memset(m_errorInfo.szErrMsg, 0, sizeof(m_errorInfo.szErrMsg));
+		iRet = DRVCardDispenser->OpenDev(szComPort,(int)dwBaudRate);
+		if(iRet != 0)
+		{
+			strcpy(m_errorInfo.szErrMsg, "connect to device failed");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			m_isDevOpened = false;
+
+			iRet =Error_DevConnFailed;
+			throw(iRet);
+		}
+		m_isDevOpened = true ;
+
+		char szErrorMsg[1024] = "";
+
+		//复位设备
+		char *sReset[10] = {NULL};
+		char PowerOnFlag[10] ="1";
+		char PowerOffFlag[10]="3";
+		sReset[1] = PowerOnFlag;
+		sReset[2] = PowerOffFlag;
+		iRet = DRVCardDispenser->ResetDev(3,sReset);
+		if(iRet != 0)
+		{
+			strcpy(m_errorInfo.szErrMsg, "hardware error");
+			m_errorInfo.dwErrMsgLen = strlen(m_errorInfo.szErrMsg);
+			iRet = Error_Hardware;
+			throw(iRet);
+		}	
+		int mSupplyBin =2, mRetainBin =1, mHoldBin =0;
+
+		DRVCardDispenser->GetDevCap(CapInfo);
+		mSupplyBin = atoi(CapInfo[0]);
+		mRetainBin = atoi(CapInfo[1]);
+		mHoldBin = atoi(CapInfo[2]);
+		iRet = Error_Succeed;
+	}catch(int eret){iRet = eret;}
+	btType = DEV_OPEN_TYPE_COM;
+	m_busy_flag = false;
+	for (int i = 0; i < 10; i++)
+	{
+		delete[]CapInfo[i];
+	}
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::TransferEnInit(int &iStatus, BYTE *&Cr1, int &lenR1, BYTE *&Cr3, int &lenR3, BYTE *&dKey, int &lenKey)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SetR2(int &iStatus, BYTE *pCr2, int lenR2)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SendWorkingKey(const char *pWorkingKey)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SAMActive(BYTE vcc)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SAMDeactivate()
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SAMWarmReset()
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SAMCommand(CmdInfo sendBuf, CmdInfo& recvBuf)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SAMQueryStatus(SAMStatus& samStatus)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SAMSelect(const int sn)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::ActiveICCardATR(CmdInfo& atrBuf)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+    ////////////////卡面打印部分,部分机型有此功能//////////////////
+ErrorCodeEnum CardIssuerClassImpl::Print(BYTE*& data, const int dataSize, const int side)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::QueryPrinterStatus()
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+//安全锁接口部分
+ErrorCodeEnum CardIssuerClassImpl::SLLoadKey(const SCIKeyInfo key)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SLSetParam(SCIParamType eType, int value)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SLLock()
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SLUnLock(const SCICheckCode checkCode, bool bTemp )
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SLGetTempData(SCITempData &ksnData, SCITempData &ramData)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::SLOpenDoor(const SCITempData data)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+//蓝牙控制部分
+ErrorCodeEnum CardIssuerClassImpl::BluetoothControl(SCIBluetoothCMD eCmd)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::BluetoothModifyKey(unsigned char *key)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::BluetoothModifyName(unsigned char *name)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::BluetoothGetVersion(char *&version)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::BluetoothGetConnectName(unsigned char *&name)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::BluetoothGetSignalStrength(unsigned char *&signal)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+
+//控制灯光
+ErrorCodeEnum CardIssuerClassImpl::LightControl(SCILightType eLight, bool bOnOff)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+ErrorCodeEnum CardIssuerClassImpl::QueryBatteryPower(int &bat)
+{
+	int iRet = 0;
+	return (ErrorCodeEnum)iRet;
+}
+
+void CardIssuerClassImpl::WAITING_LOOP()
+{
+	while (1)
+	{
+
+		if (m_signal_get_flag == false)
+			break;
+
+	}
+}

+ 215 - 0
DevAdapter/nantian/cardissuer.1.1/cardissuer.nantian.1.1.h

@@ -0,0 +1,215 @@
+#ifndef LIBFRAMEWORK_CARDISSUER_IMPL_H
+#define LIBFRAMEWORK_CARDISSUER_IMPL_H
+
+#include "../../DevAdapter/include/CardIssuerClass.h"
+
+#include "../include/CILIX_AUX_UTILS.h"
+
+//DRV头文件
+#include "../include/DRV_CardDispenser.h"
+
+#include "dlfcn.h"
+#include "stddef.h"
+
+typedef DRV_CardDispenser *(*pCreate_DRV_CardDispenser)();
+typedef void (*pDestroy_DRV_CardDispenser)(DRV_CardDispenser *p);
+
+class CardIssuerClassImpl : public CardIssuerClass
+{
+public:
+    CardIssuerClassImpl();
+    ~CardIssuerClassImpl();
+
+
+    //DeviceBaseClass
+    ErrorCodeEnum GetDevCategory(DevCategoryInfo &devCategory);
+    ErrorCodeEnum Reset();
+    ErrorCodeEnum DevClose();
+    ErrorCodeEnum GetLastErr(DevErrorInfo &devErrInfo);
+
+public:
+
+    virtual ErrorCodeEnum DevOpen(DWORD dwPort, DWORD dwBaudRate);
+    virtual ErrorCodeEnum GetDevStatus(CardIssuerStatus& devStatus);
+    virtual ErrorCodeEnum GetDeviceSN(char*& pDevSN);
+    virtual ErrorCodeEnum MoveCard(CardPosEnum eCardPos, int hopperNo = 1);
+    //
+    //	Set card entry
+    //
+    virtual ErrorCodeEnum SetCardInType(CardInEnum eCardIn);
+
+    //
+    //	Read data from magnetic track.
+    //
+    virtual ErrorCodeEnum MagRead(MagTracks& magTracks);
+
+    //
+    //	Write data to magnetic track.
+    //
+    virtual ErrorCodeEnum MagWrite(MagTracks magTracks, MagWriteModeEnum eWriteMode);
+    //
+    //	Set retract counter
+    //
+    virtual ErrorCodeEnum SetRetractCounter(DWORD dwCount);
+    //
+    //	Set issuer counter
+    //	hopperNo:多卡箱发卡时指定发卡箱号(面对发卡机,从左往右依次是1,2,3,...号卡箱)
+    //
+    virtual ErrorCodeEnum SetIssuerCounter(DWORD dwCount, int hopperNo = 1);
+    //
+    //	Active contact IC card
+    //
+    virtual ErrorCodeEnum ActiveICCard();
+    //
+    //	Move IC card to contact position
+    //
+    virtual ErrorCodeEnum ContactIC();
+    //
+    //	Release IC contact
+    //
+    virtual ErrorCodeEnum ReleaseIC();
+    //
+    //	Warm reset card(IC)
+    //
+    virtual ErrorCodeEnum WarmReset();
+    //
+    //	APDU:Application Protocol Data Unit
+    //	CmdSend.lpCmd:Command-APDU
+    //	CmdRecv.lpData:Response-APDU
+    //
+    virtual ErrorCodeEnum ICCommand(CmdInfo sendBuf, CmdInfo& recvBuf);
+    //////////////////SAM 卡操作部分////////////////////
+    virtual ErrorCodeEnum SAMActive(BYTE vcc = 0x30);
+    virtual ErrorCodeEnum SAMDeactivate();
+    virtual ErrorCodeEnum SAMWarmReset();
+    virtual ErrorCodeEnum SAMCommand(CmdInfo sendBuf, CmdInfo& recvBuf);
+    virtual ErrorCodeEnum SAMQueryStatus(SAMStatus& samStatus);
+    virtual ErrorCodeEnum SAMSelect(const int sn);
+    virtual ErrorCodeEnum ActiveICCardATR(CmdInfo& atrBuf);
+    ////////////////卡面打印部分,部分机型有此功能//////////////////
+    virtual ErrorCodeEnum Print(BYTE*& data, const int dataSize, const int side);
+    virtual ErrorCodeEnum QueryPrinterStatus();
+
+    ////////////////////////////////////////////////////////////////////////////
+    ////////非接(IC)部分 start,没有此部分,在接口实现中直接返回Error_NotImpl///////////////
+    ////////////////////////////////////////////////////////////////////////////
+    //	Active contactless IC card(Type A,B,Mifare)
+    //	The first,second,third activation order decided by fstType,scdType,thdType respectively
+    //	fstType,scdType,thdType can be one of 'A','B','M','0'(30H,no type)
+    //	outType indicates the type of  activation result
+    //
+    virtual ErrorCodeEnum ActiveContactlessICCard(char fstType, char scdType, char thdType, char& outType);
+    //
+    //	Deactivate contact IC card
+    //
+    virtual ErrorCodeEnum DeactivateICCard();
+    //
+    //	Deactivate contactless IC card
+    //
+    virtual ErrorCodeEnum DeactContactlessICCard();
+    //
+    //	RF Mifare Classic protocol operation
+    //	Arguments:
+    //	- eFunType:function type as load key,authentication and so on
+    //	- sendBuf:[parameter][data]
+    //	- recvBuf:[status(1byte)][return data]
+    //
+    virtual ErrorCodeEnum MifareCommand(MifareFuctionEnum eFunType, CmdInfo sendBuf, CmdInfo& recvBuf);
+    //
+    //	RF Type A,B command.
+    //	APDU:Application Protocol Data Unit
+    //	Arguments:
+    // 	- CmdSend.lpCmd:Command-APDU
+    // 	- CmdRecv.lpData:Response-APDU
+    //
+    virtual ErrorCodeEnum RFTypeABCommand(CmdInfo sendBuf, CmdInfo& recvBuf);
+    ////////非接(IC)部分 end/////////////////////////////////////////////////////////
+
+    virtual ErrorCodeEnum DevOpenEx(DWORD dwPort, DWORD dwBaudRate, BYTE btOpenType, const char* pDevSN, BYTE& btType);
+
+    /////////////////////////////////////////////////////////////////////////
+    ///以下是便携式卡机特有API,接口实现中其他机型直接返回Error_NotImpl即可//
+    /////////////////////////////////////////////////////////////////////////
+
+    //	返回值Error_Succeed表示成功,其他值表示失败
+    //	iStatus   0:成功   -1:银行公钥不存在   -2:产生设备密钥故障  -x:其他厂商自定义故障
+    //	Cr1:随机数r1的密文; Cr3:随机数r3的密文,dKey:用银行公钥加密的设备公钥密文
+    //	r1,r3第16字节为数据完整性校验字节,例如r1为B1B2...B15B16,则B16=B1^B2^...^B15
+    virtual ErrorCodeEnum TransferEnInit(int& iStatus, BYTE*& Cr1, int& lenR1, BYTE*& Cr3, int& lenR3, BYTE*& dKey, int& lenKey);
+
+    //	返回值Error_Succeed表示成功,其他值表示失败
+    //	iStatus   0:成功   -x:厂商自定义故障
+    //	r2第16字节为数据完整性校验字节,例如r2为B1B2...B15B16,则B16=B1^B2^...^B15
+    virtual ErrorCodeEnum SetR2(int& iStatus, BYTE* pCr2, int lenR2);
+    //
+    //	设置会话密钥
+    //	pWorkingKey:会话密钥,传递16进制的字符形式,例如0x123456FFAB  --> "123456FFAB"
+    virtual ErrorCodeEnum SendWorkingKey(const char* pWorkingKey);
+
+    //安全锁接口部分 begin
+    virtual ErrorCodeEnum SLLoadKey(const SCIKeyInfo key);
+    //case ParamBeep: value:0,close beep;value:1,open beep
+    //case ParamLed: value:0,close led;value:1,open led
+    //case ParamLevelTime: value:the duration of level,100ms per unit
+    //		ex.	the value 10 means duration time is 1 second
+    virtual ErrorCodeEnum SLSetParam(SCIParamType eType, int value);
+    virtual ErrorCodeEnum SLLock();
+    virtual ErrorCodeEnum SLUnLock(const SCICheckCode checkCode, bool bTemp = true);
+    virtual ErrorCodeEnum SLGetTempData(SCITempData& ksnData, SCITempData& ramData);
+    virtual ErrorCodeEnum SLOpenDoor(const SCITempData data);
+    //安全锁接口部分 end
+
+    //蓝牙控制部分 start
+    //蓝牙指令控制,命令参看SCIBluetoothCMD说明
+    virtual ErrorCodeEnum BluetoothControl(SCIBluetoothCMD eCmd);
+    //修改配对密码
+    virtual ErrorCodeEnum BluetoothModifyKey(unsigned char* key);
+    //修改蓝牙设备名称
+    virtual ErrorCodeEnum BluetoothModifyName(unsigned char* name);
+    //获取版本信息
+    virtual ErrorCodeEnum BluetoothGetVersion(char*& version);
+    //获取连接设备名称
+    virtual ErrorCodeEnum BluetoothGetConnectName(unsigned char*& name);
+    //获取连接设备信号强度
+    virtual ErrorCodeEnum BluetoothGetSignalStrength(unsigned char*& signal);
+    //蓝牙控制部分 end
+
+    //控制灯光
+    //eLight:所控制的灯 ;
+    //bOnOff:true 亮灯;fasle 灭灯
+    virtual ErrorCodeEnum LightControl(SCILightType eLight, bool bOnOff);
+    //以百分比数值返回剩余电量(1-100),例如剩余51%,则bat赋值为51
+    virtual ErrorCodeEnum QueryBatteryPower(int& bat);
+private:
+    int m_mode;
+public:
+	//DRV实现对象
+    void *dplHandle;
+    pCreate_DRV_CardDispenser Create_DRV_CardDispenser;
+    pDestroy_DRV_CardDispenser Destroy_DRV_CardDispenser;
+    DRV_CardDispenser *DRVCardDispenser;
+	
+	DevErrorInfo m_errorInfo;
+	bool  m_isDevOpened;
+	bool  m_isCanceled;
+
+	int   m_SetCardInTypeFlag;
+	
+	bool LoadNTDRVDLL();
+	
+	void WAITING_LOOP();
+
+	bool m_busy_flag;
+	bool m_signal_get_flag;
+	bool m_CardInTypeFlag;
+
+	ErrorCodeEnum m_StatusErrorCode;
+	CardIssuerStatus tempStatus;
+
+    int RetainBox;
+	
+	CILIXTrace *m_trace;
+};
+
+
+#endif //LIBFRAMEWORK_CARDISSUER_IMPL_H

+ 16 - 0
DevAdapter/nantian/idcer.1.1/CMakeLists.txt

@@ -0,0 +1,16 @@
+rvc_dev_define_module("IDCertificate")
+set(${MODULE_PREFIX}_VENDOR "nantian")
+set(${MODULE_PREFIX}_VERSION "1")
+set(${MODULE_PREFIX}_BATCH "1")
+
+set(${MODULE_PREFIX}_SRCS SHARED
+        idcertificate.nantian.1.1.cpp
+        GVar.cpp
+        )
+
+rvc_dev_config_library(${MODULE_NAME} ${MODULE_PREFIX})
+
+rvc_dev_target_install(${MODULE_FULL_NAME})
+
+find_package(Threads)
+target_link_libraries(${MODULE_FULL_NAME} ${CMAKE_THREAD_LIBS_INIT})

+ 124 - 0
DevAdapter/nantian/idcer.1.1/GVar.cpp

@@ -0,0 +1,124 @@
+#include "GVar.h"
+
+GVar::GVar()
+{
+	m_pAlloc = new CILIX_Allocator();
+	m_pDRVObj = NULL;
+	m_bIsConnected = FALSE;
+	m_bIsCancel = FALSE;
+	m_hInsDRV = NULL;
+	m_pTrace = new CILIXTrace(NULL,"ZQ_689S","idcer.Nantian");
+	memset(m_IniFilePath,0,sizeof(m_IniFilePath));
+        sprintf(m_IniFilePath,"./dev/ZQ_689S.ini");
+	memset(m_errMsg,0,MAX_LEN);
+        TheardEnd = false;
+        ReadFlg = false;
+}
+
+GVar::~GVar()
+{
+	if (m_hInsDRV)
+	{
+		//释放动态库句柄
+		m_pDestroyDRV(m_pDRVObj);
+		//FreeLibrary(m_hInsDRV);
+		dlclose(m_hInsDRV);
+		m_hInsDRV = NULL;
+		m_pDRVObj = NULL;
+	}
+
+	if (m_pTrace)
+	{
+		delete m_pTrace;
+		m_pTrace = NULL;
+	}
+	
+	if (m_pAlloc)
+	{
+		delete m_pAlloc;
+		m_pAlloc = NULL;
+	}
+
+}
+
+int GVar::LoadDRVDLL()
+{
+	CILIX_AUX_X::CILIX_GetModuleCurPath(m_dllPath);
+	//char szPathDRV[512] = { 0 };
+	strcat(m_dllPath,"libDRV_ZQ_689S.nantian.so");
+       // sprintf(szPathDRV, "./dev/nantian.libDRV_ZQ_689S.so");
+	m_hInsDRV = dlopen(m_dllPath,RTLD_LAZY);
+	if (!m_hInsDRV)
+	{
+		m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "LoadDRVDLL",
+			"DRV Load error, path:%s", m_dllPath);
+		return -1;
+	}
+	else
+	{
+		m_pCretateDRV = (pCreateDRV)dlsym(m_hInsDRV, "Create_DRV_IDCardReader");
+		m_pDestroyDRV = (pDestroyDRV)dlsym(m_hInsDRV, "Destroy_DRV_IDCardReader");
+	}
+	if (!m_pCretateDRV || !m_pDestroyDRV)
+	{
+		m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "LoadDRVDLL",
+			"DRV Dll dlsym error");
+		return -2;
+	}
+	else
+	{
+		m_pDRVObj = m_pCretateDRV();
+	}
+	return 0;
+}
+
+void GVar::FreeArryBuf(void ** pBuf, int len)
+{
+	if (pBuf == NULL || len == 0)
+	{
+		return;
+	}
+	for (size_t i = 0; i < len; i++)
+	{
+		if (pBuf[i] != NULL)
+		{
+			delete pBuf[i];
+			pBuf[i] = NULL;
+		}
+	}
+}
+
+void GVar::SwitchNationToCode(char* pNation, char* pCode)
+{
+	if (pNation == NULL ||
+		pCode == NULL)
+	{
+		return;
+	}
+	if (strcmp(pNation, "柯尔人") == 0)
+	{
+		strcpy(pCode, "57");
+	}
+	if (strcmp(pNation, "穿青人") == 0)
+	{
+		strcpy(pCode, "59");
+	}
+	if (strcmp(pNation, "亻革家人") == 0)
+	{
+		strcpy(pCode, "60");
+	}
+	if (strcmp(pNation, "摩梭人") == 0)
+	{
+		strcpy(pCode, "95");
+	}
+}
+
+
+void GVar::AddCharToDate(char* SourceStr, char Addchar)
+{
+	string strTemp(SourceStr);
+	strTemp.insert(4, 1, Addchar);
+	strTemp.insert(7, 1, Addchar);
+	memcpy(SourceStr, strTemp.c_str(), strTemp.size());
+}
+

+ 114 - 0
DevAdapter/nantian/idcer.1.1/GVar.h

@@ -0,0 +1,114 @@
+#ifndef __GVAR_H__
+#define __GVAR_H__
+
+#define MID_LEN 128
+#define MAX_LEN 1024
+#define MIN_LEN 16
+
+#include "../include/DRV_IDCardReader.h"
+#include "../../include/IDCerClass.h"
+#include "../include/CILIX_AUX_UTILS.h"
+#include <iostream>
+#include <algorithm>
+#include <functional>
+#include <time.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <pthread.h>
+using namespace std;
+
+typedef DRV_IDCardReader *(*pCreateDRV)(void);
+typedef DRV_IDCardReader *(*pDestroyDRV)(DRV_IDCardReader *);
+
+#pragma once
+class GVar
+{
+public:
+	GVar();
+	~GVar();
+
+public:
+	pCreateDRV	m_pCretateDRV;
+	pDestroyDRV	m_pDestroyDRV;
+	//
+	DRV_IDCardReader *m_pDRVObj;
+	void* m_hInsDRV;
+public:
+	//日志记录指针
+	CILIXTrace *m_pTrace;		
+	//加载动态库成功标记
+	BOOL m_bIsLoadLib;		
+	//设备是否连接标记
+	BOOL m_bIsConnected;		
+	//取消标记
+	BOOL m_bIsCancel;	
+	//内存分配器对象
+	CILIX_Allocator *m_pAlloc;	
+	bool TheardEnd;
+    bool ReadFlg;
+	//事件处理对象
+	BOOL g_flag;
+	//身份证字段分割符
+	char m_filedSep[MIN_LEN];		
+	//是否处理生日长度 0--不处理,1--处理
+	int	 m_bIsDealBirth;		
+	//身份证反面图片路径
+	char m_backPath[MAX_LEN];
+	//身份证正面图片路径
+	char m_frontPath[MAX_LEN];
+	//身份证头像图片路径
+	char m_headPath[MAX_LEN];
+	//身份证图片保存路径	
+	char m_savePath[MAX_LEN];
+	//扫描读卡完成后,是否自动退卡 0--不退卡,1--退卡
+	int m_autoEject;	
+	//正反面图片类型,0--bmp,1--jpg
+	int	m_picType;	
+	//头像图片类型,0--bmp,1--jpg
+	int	m_headPicType;		
+	//dll加载的路径
+	char m_dllPath[MAX_LEN];
+	//配置文件的路径
+	char m_IniFilePath[MAX_LEN];
+	//物理名
+	char m_physicName[MID_LEN];
+
+	char m_errMsg[MAX_LEN];
+
+public:
+	int LoadDRVDLL();
+
+    void SwitchNationToCode(char* pNation, char* pCode);
+
+	void FreeArryBuf(void **pBuf, int len);
+
+	void AddCharToDate(char* SourceStr, char Addchar);
+	/************************************************************************/
+	/*读卡操作相关                                                            */
+	/***********************************************************************
+public:
+
+	//
+	int ScanReadCard(long lTimeOut, char *pIDInfo, int *piIDInfoLen,
+		char *pIDFP, int *piIDFPLen, char *pSavePath, char *pFrontImg,
+		char *pBackImg, char *pHeadImg);
+
+	int FormatIDInfo(char *pIDInfo, int *piIDInfoLen, char **sIDXData,
+		char *pFiledSep, char *pHeadImg);
+
+	int FormatGATInfo(char *pIDInfo, int *piIDInfoLen, char **sIDXData,
+		char *pFiledSep, char *pHeadImg);
+
+	int FormatFRNInfo(char *pIDInfo, int *piIDInfoLen, char **sIDXData,
+		char *pFiledSep, char *pHeadImg);
+
+	int ReadDataFromFile(char *pFilePath, unsigned char *pBufData,
+		int iExpectReadDataLen);
+*/
+
+};
+#endif
+
+
+
+

+ 1216 - 0
DevAdapter/nantian/idcer.1.1/idcertificate.nantian.1.1.cpp

@@ -0,0 +1,1216 @@
+#include "GVar.h"
+#include "idcertificate.nantian.1.1.h"
+GVar g_pGvar;
+//自动日志对象
+#define _AUTOTRACE_(M)  CILIXAutoTrace  __at(g_pGvar.m_pTrace,#M,&iRet);
+
+
+IDCERTIFICATE_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass *&baseObj)
+{
+	baseObj = new IDCardReaderNantian();
+	if (baseObj == NULL)
+		return Error_Null;
+	else
+		return Error_Succeed;
+
+}
+IDCERTIFICATE_API ErrorCodeEnum ReleaseDevComponent(DeviceBaseClass *&pBaseObj)
+{
+	if (pBaseObj == NULL)
+		return Error_Param;
+	IDCardReaderNantian* pTmp = (IDCardReaderNantian*)(pBaseObj);
+	delete pTmp;
+	pTmp = NULL;
+	return Error_Succeed;
+}
+
+
+IDCardReaderNantian::IDCardReaderNantian()
+{
+    int ret = g_pGvar.LoadDRVDLL();
+    g_pGvar.m_pTrace->WriteTrace("IDCardReader", "idcer.Nantian.1.1.so - 1.0.0.5");
+	
+}
+
+IDCardReaderNantian::~IDCardReaderNantian()
+{
+	
+}
+
+ErrorCodeEnum IDCardReaderNantian::DevOpen(DWORD dwPort)
+{
+    ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(DevOpen)
+	try
+	{
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevOpen",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+		
+		char sPort[32] = { 0 };
+		int iBaud = 0;
+
+		g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "Open",
+			"Call DRV OpenDev Method, sPort:[%s], iBaud:[%d]",
+			sPort, iBaud);
+		iRet = g_pGvar.m_pDRVObj->OpenDev(sPort, iBaud);
+		g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "Open",
+			"DRV OpenDev return:[%d]", iRet);
+		if(iRet != 0)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevOpen",
+				"OpenDevice,return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "open device error, code:%d", iRet);
+			throw Error_DevCommFailed;
+		}
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+	return eRet;
+
+}
+
+ ErrorCodeEnum IDCardReaderNantian::Reset()
+{
+	ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(Reset)
+	try
+	{
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevOpen",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+		
+		iRet =g_pGvar.m_pDRVObj->ResetDev(2,NULL);
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "Reset",
+				"ResetDevice error, return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "reset device error, code:%d", iRet);
+			throw Error_Hardware;
+		}
+		//复位后重新连接设备
+		iRet = g_pGvar.m_pDRVObj->CloseDev();
+		char sPort[32] = { 0 };
+		int iBaud = 0;
+		iRet = g_pGvar.m_pDRVObj->OpenDev(sPort, iBaud);
+		g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "Open",
+			"DRV OpenDev return:[%d]", iRet);
+		if(iRet != 0)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevOpen",
+				"OpenDevice,return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "open device error, code:%d", iRet);
+			throw Error_DevCommFailed;
+		}
+		throw Error_Succeed;
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+	return eRet;
+}
+
+ ErrorCodeEnum IDCardReaderNantian::DevClose()
+{
+	ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(DevClose)
+	
+	try
+	{
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevOpen",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+		//停止等待进卡线程
+		g_pGvar.m_bIsCancel = true;
+		usleep(150000);
+		iRet = g_pGvar.m_pDRVObj->CloseDev();
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevClose",
+				"close dev error, return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "close device error, code:%d", iRet);
+			throw Error_Hardware;
+		}
+
+		throw Error_Succeed;
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+	return eRet;
+}
+
+ ErrorCodeEnum IDCardReaderNantian::GetLastErr(DevErrorInfo& devErrInfo)
+{
+	memset(&devErrInfo, 0, sizeof(DevErrorInfo));
+	devErrInfo.dwErrMsgLen = strlen(g_pGvar.m_errMsg);
+	memset(devErrInfo.szErrMsg, 0, MAX_DEV_ERROR_MSG_LEN);
+	memcpy(devErrInfo.szErrMsg, g_pGvar.m_errMsg, devErrInfo.dwErrMsgLen);
+	return Error_Succeed;
+}
+
+ ErrorCodeEnum IDCardReaderNantian::GetDevCategory(DevCategoryInfo& devCategory)
+{
+
+	ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(GetDevCategory)
+
+	char *sDevStatus[MIN_LEN];
+	
+	try
+	{
+		strcpy(devCategory.szType, "IDCertificate");
+		strcpy(devCategory.szVendor, "Nantian");
+		strcpy(devCategory.szModel, "STYLE=IG#FUNCTION=ITF");
+		devCategory.version.wMajor = 1;
+		devCategory.version.wMinor = 0;
+		devCategory.version.wRevision = 0;
+		devCategory.version.wBuild = 1;
+		devCategory.eState = DEVICE_STATUS_NORMAL;
+
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevOpen",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+
+		//查询设备状态
+		for (int i = 0; i < MIN_LEN; i++)
+		{
+			sDevStatus[i] = new char[MID_LEN];
+			memset(sDevStatus[i], 0, MID_LEN);
+		}
+		iRet = g_pGvar.m_pDRVObj->GetDevStatus(0, sDevStatus);
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "GetDevCategory",
+				"GetDeviceStatus error return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "device is offline, code:%d", iRet);
+			devCategory.eState = DEVICE_STATUS_NOT_READY;
+			throw Error_Hardware;
+		}
+		else
+		{
+			switch (atoi(sDevStatus[1]))
+			{
+			case IDCARDREADER_DEVBUSY:
+				//设备掉电
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				strcpy(g_pGvar.m_errMsg, "device BUSY");
+				devCategory.eState = DEVICE_STATUS_CONNECTING;
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "GetDevCategory","device BUSY");
+			break;			
+			case IDCARDREADER_DEVHWERROR:
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				strcpy(g_pGvar.m_errMsg, "device HWERROR");
+				devCategory.eState = DEVICE_STATUS_FAULT;
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "GetDevCategory","device HWERROR");
+			break;
+			case IDCARDREADER_DEVOFFLINE:
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				strcpy(g_pGvar.m_errMsg, "device OFFLINE");
+				devCategory.eState = DEVICE_STATUS_FAULT;
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "GetDevCategory","device OFFLINE");
+			break;
+			}
+			switch (atoi(sDevStatus[2]))
+			{
+			case IDCARDREADER_MEDIAJAMMED:
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				strcpy(g_pGvar.m_errMsg, "device jamed");
+				devCategory.eState = DEVICE_STATUS_FAULT;
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "GetDevCategory","device jamed");
+			break;
+			}
+		}
+		throw Error_Succeed;
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+        //if (sDevStatus != NULL)
+        //g_pGvar.FreeArryBuf((void **)sDevStatus, MIN_LEN);
+	return eRet;
+}
+
+ ErrorCodeEnum IDCardReaderNantian::IDCerAuthenticate()
+{
+	ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(IDCerAuthenticate)
+
+	int idxFlag = 0;
+	int iCardType = 0;
+	char *sIDXData[MID_LEN];
+	char *sDevStatus[MIN_LEN];
+	try
+	{
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerAuthenticate",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+        if(g_pGvar.TheardEnd)
+        {
+            g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerAuthenticate",
+				"卡未插入");
+            throw Error_DevMedia;
+        }
+        if(g_pGvar.ReadFlg)
+        {
+            iRet = g_pGvar.m_pDRVObj->EjectCard();
+            usleep(500000);
+            iRet = g_pGvar.m_pDRVObj->InsertCard(NULL);       
+        }
+		for (int i = 0; i < MIN_LEN; i++)
+		{
+			sDevStatus[i] = new char[MID_LEN];
+			memset(sDevStatus[i], 0, MID_LEN);
+		}
+		iRet = g_pGvar.m_pDRVObj->GetDevStatus(idxFlag, sDevStatus);
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "GetDevCategory",
+				"GetDeviceStatus error return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "device is offline, code:%d", iRet);
+			//budevCategory.eState = DEVICE_STATUS_NOT_READY;
+			throw Error_Hardware;
+		}
+		else
+		{
+			if (atoi(sDevStatus[1]) == IDCARDREADER_DEVONLINE)
+			{
+				if (atoi(sDevStatus[2]) == IDCARDREADER_MEDIAPRESENT)
+				{
+					//第2个传感器(读卡位置)检测有卡
+					//读卡
+					/*SEA_AUX_X::SAU_GetModuleCurPath(szDllPath);
+					sprintf(szHeadPath, "%szp.bmp", szDllPath);
+					DeleteFile(szHeadPath);*/
+					for (size_t i = 0; i < MID_LEN; i++)
+					{
+						sIDXData[i] = new char[MAX_LEN];
+						memset(sIDXData[i], 0, MAX_LEN);
+					}
+					g_pGvar.ReadFlg = true;
+					iRet = g_pGvar.m_pDRVObj->ReadIDXData(sIDXData);
+					if (iRet != E_DRVBASE_SUCCESS)
+					{
+						g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerAuthenticate",
+							"ReadIDXData error,return:%d", iRet);
+						memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+						sprintf(g_pGvar.m_errMsg, "read card error, code:%d", iRet);
+						throw Error_DevMedia;
+					}
+					else
+					{
+						throw Error_Succeed;
+					}
+				}
+				else
+				{
+					throw Error_Unexpect;
+				}
+			}
+			else
+			{
+				throw Error_Unexpect;
+			}
+		}
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+        /*if (sIDXData != NULL)
+	g_pGvar.FreeArryBuf((void **)sIDXData, MID_LEN);
+	if (sDevStatus != NULL)
+        g_pGvar.FreeArryBuf((void **)sDevStatus, MIN_LEN);*/
+	return eRet;
+}
+
+ ErrorCodeEnum IDCardReaderNantian::IDCerGetDataEx(IDCerInfoEx &idCerInfoEx)
+{
+	ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(IDCerGetDataEx)
+
+	int idxFlag = 0;
+	memset(&idCerInfoEx, 0, sizeof(IDCerInfoEx));
+	char szDllPath[1024] = { 0 };
+	char szHeadPath[1024] = { 0 };
+	int iCardType = 0;
+	char *sIDXData[MID_LEN];
+	char *sDevStatus[MIN_LEN];
+	try
+	{
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevOpen",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+        if(g_pGvar.ReadFlg)
+        {
+            iRet = g_pGvar.m_pDRVObj->EjectCard();
+            usleep(500000);
+            iRet = g_pGvar.m_pDRVObj->InsertCard(NULL);       
+        }
+		//查询设备状态
+		for (int i = 0; i < MIN_LEN; i++)
+		{
+			sDevStatus[i] = new char[MID_LEN];
+			memset(sDevStatus[i], 0, MID_LEN);
+		}
+		iRet = g_pGvar.m_pDRVObj->GetDevStatus(idxFlag, sDevStatus);
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetDataEx",
+				"GetDeviceStatus error return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "device is offline, code:%d", iRet);
+			throw Error_Hardware;
+		}
+		else
+		{
+			if (atoi(sDevStatus[2]) != IDCARDREADER_MEDIAPRESENT)
+			{
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetDataEx",
+					"no card in device");
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				strcpy(g_pGvar.m_errMsg, "no card in device");
+				throw Error_DevMedia;
+			}
+		}
+		for (size_t i = 0; i < MID_LEN; i++)
+		{
+			sIDXData[i] = new char[MAX_LEN];
+			memset(sIDXData[i], 0, MAX_LEN);
+		}			
+		iRet = g_pGvar.m_pDRVObj->ReadIDXData(sIDXData);
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetDataEx",
+				"ReadAllIDInfo error,return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "read card error, code:%d", iRet);
+			throw Error_Hardware;
+		}
+        g_pGvar.ReadFlg = true;
+		char szExpireStart[16] = { 0 };
+		char szExpireEnd[16] = { 0 };
+		//国内二代证
+		if (atoi(sIDXData[0]) == 1)
+		{
+			if (strstr(sIDXData[3], "族"))
+			{
+				int len = strlen(sIDXData[3]);
+				idCerInfoEx.nation.dwSize = strlen(sIDXData[3]) - (strlen("族"));
+				memcpy(idCerInfoEx.nation.data, sIDXData[3], idCerInfoEx.nation.dwSize);
+				idCerInfoEx.nation.data[idCerInfoEx.nation.dwSize] = '\0';
+			}
+			else
+			{
+				idCerInfoEx.nation.dwSize = strlen(sIDXData[3]);
+				memcpy(idCerInfoEx.nation.data,sIDXData[3], idCerInfoEx.nation.dwSize);
+				idCerInfoEx.nation.data[idCerInfoEx.nation.dwSize] = '\0';
+			}
+			//20200324 by qhw
+			//如果民族超过56个名族代码,则直接返回代码
+			char sTmpCode[1024] = { 0 };
+			g_pGvar.SwitchNationToCode(idCerInfoEx.nation.data, sTmpCode);
+			if (strlen(sTmpCode) > 0)
+			{
+				idCerInfoEx.nation.dwSize = strlen(sTmpCode);
+				memcpy(idCerInfoEx.nation.data, sTmpCode, idCerInfoEx.nation.dwSize);
+				idCerInfoEx.nation.data[idCerInfoEx.nation.dwSize] = '\0';
+			}
+
+			idCerInfoEx.name.dwSize = strlen(sIDXData[1]);
+			memcpy(idCerInfoEx.name.data, sIDXData[1], idCerInfoEx.name.dwSize);
+			idCerInfoEx.name.data[idCerInfoEx.name.dwSize] = '\0';
+
+			idCerInfoEx.idno.dwSize = strlen(sIDXData[6]);
+			memcpy(idCerInfoEx.idno.data, sIDXData[6], idCerInfoEx.idno.dwSize);
+			idCerInfoEx.idno.data[idCerInfoEx.idno.dwSize] = '\0';
+
+			idCerInfoEx.sex.dwSize = strlen(sIDXData[2]);
+			memcpy(idCerInfoEx.sex.data, sIDXData[2], idCerInfoEx.sex.dwSize);
+			idCerInfoEx.sex.data[idCerInfoEx.sex.dwSize] = '\0';
+
+			//处理生日日期
+			string str(sIDXData[4]);
+			str.insert(4, "年");
+			str.insert(6 + strlen("年"), "月");
+			str.insert(str.size(), "日");
+
+			char p[32] = { 0 };
+			strcpy(p, str.c_str());
+			idCerInfoEx.birthday.dwSize = strlen(p);
+			memcpy(idCerInfoEx.birthday.data, p, idCerInfoEx.birthday.dwSize);
+			idCerInfoEx.birthday.data[idCerInfoEx.birthday.dwSize] = '\0';
+
+			idCerInfoEx.address.dwSize = strlen(sIDXData[5]);
+			memcpy(idCerInfoEx.address.data, sIDXData[5], idCerInfoEx.address.dwSize);
+			idCerInfoEx.address.data[idCerInfoEx.address.dwSize] = '\0';
+
+			idCerInfoEx.newAddress.dwSize = 0;
+			memset(idCerInfoEx.newAddress.data, 0, MAX_IDCER_INFO_SIZE);
+			idCerInfoEx.newAddress.data[idCerInfoEx.newAddress.dwSize] = '\0';
+
+			idCerInfoEx.department.dwSize = strlen(sIDXData[7]);
+			memcpy(idCerInfoEx.department.data, sIDXData[7], idCerInfoEx.department.dwSize);
+			idCerInfoEx.department.data[idCerInfoEx.department.dwSize] = '\0';
+
+			memcpy(szExpireStart, sIDXData[8],strlen(sIDXData[8]));
+			memcpy(szExpireEnd, sIDXData[9],strlen(sIDXData[9]));
+g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "IDCerGetDataEx",
+				"EndData = %s", szExpireEnd);
+			g_pGvar.AddCharToDate(szExpireStart, '.');
+			/*if (strcmp(szExpireEnd, "长期") != NULL)
+			{
+				g_pGvar.AddCharToDate(szExpireEnd, '.');
+			}*/
+char a[10] = {0};
+sprintf(a,"2");
+            if (strncmp(szExpireEnd,a,1)==0)
+			{
+  g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "IDCerGetDataEx",
+				"EndData1 = %s", szExpireEnd);
+				g_pGvar.AddCharToDate(szExpireEnd, '.');
+          
+			}
+             else
+            {
+                memset(szExpireEnd,0,sizeof(szExpireEnd));
+                strcpy(szExpireEnd,"长期");
+g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "IDCerGetDataEx",
+				"EndData2 = %s", szExpireEnd);
+            }
+			idCerInfoEx.startDate.dwSize = strlen(szExpireStart);
+			memcpy(idCerInfoEx.startDate.data, szExpireStart, idCerInfoEx.startDate.dwSize);
+			idCerInfoEx.startDate.data[idCerInfoEx.startDate.dwSize] = '\0';
+
+			idCerInfoEx.endDate.dwSize = strlen(szExpireEnd);
+			memcpy(idCerInfoEx.endDate.data, szExpireEnd, idCerInfoEx.endDate.dwSize);
+			idCerInfoEx.endDate.data[idCerInfoEx.endDate.dwSize] = '\0';
+
+			idCerInfoEx.photoPath.dwSize = strlen(sIDXData[13]);
+			memcpy(idCerInfoEx.photoPath.data, sIDXData[13], idCerInfoEx.photoPath.dwSize);
+			idCerInfoEx.photoPath.data[idCerInfoEx.photoPath.dwSize] = '\0';
+		}
+		else if (atoi(sIDXData[0]) == 2)
+		{
+			//外国人居住证
+			idCerInfoEx.name.dwSize = strlen(sIDXData[5]);
+			memcpy(idCerInfoEx.name.data, sIDXData[5], idCerInfoEx.name.dwSize);
+			idCerInfoEx.name.data[idCerInfoEx.name.dwSize] = '\0';
+
+			idCerInfoEx.sex.dwSize = strlen(sIDXData[2]);
+			memcpy(idCerInfoEx.sex.data, sIDXData[2], idCerInfoEx.sex.dwSize);
+			idCerInfoEx.sex.data[idCerInfoEx.sex.dwSize] = '\0';
+
+			//处理生日日期
+			string str(sIDXData[8]);
+			str.insert(4, "年");
+			str.insert(6 + strlen("年"), "月");
+			str.insert(str.size(), "日");
+
+			char p[32] = { 0 };
+			strcpy(p, str.c_str());
+			idCerInfoEx.birthday.dwSize = strlen(p);
+			memcpy(idCerInfoEx.birthday.data, p, idCerInfoEx.birthday.dwSize);
+			idCerInfoEx.birthday.data[idCerInfoEx.birthday.dwSize] = '\0';
+
+			idCerInfoEx.idno.dwSize = strlen(sIDXData[3]);
+			memcpy(idCerInfoEx.idno.data, sIDXData[3], idCerInfoEx.idno.dwSize);
+			idCerInfoEx.idno.data[idCerInfoEx.idno.dwSize] = '\0';
+
+			idCerInfoEx.department.dwSize = strlen(sIDXData[10]);
+			memcpy(idCerInfoEx.department.data, sIDXData[10], idCerInfoEx.department.dwSize);
+			idCerInfoEx.department.data[idCerInfoEx.department.dwSize] = '\0';
+
+			g_pGvar.AddCharToDate(sIDXData[6], '.');
+			g_pGvar.AddCharToDate(sIDXData[7], '.');
+			idCerInfoEx.startDate.dwSize = strlen(sIDXData[6]);
+			memcpy(idCerInfoEx.startDate.data, sIDXData[6], idCerInfoEx.startDate.dwSize);
+			idCerInfoEx.startDate.data[idCerInfoEx.startDate.dwSize] = '\0';
+
+			idCerInfoEx.endDate.dwSize = strlen(sIDXData[7]);
+			memcpy(idCerInfoEx.endDate.data, sIDXData[7], idCerInfoEx.endDate.dwSize);
+			idCerInfoEx.endDate.data[idCerInfoEx.endDate.dwSize] = '\0';
+
+			idCerInfoEx.photoPath.dwSize = strlen(sIDXData[14]);
+			memcpy(idCerInfoEx.photoPath.data, sIDXData[14], idCerInfoEx.photoPath.dwSize);
+			idCerInfoEx.photoPath.data[idCerInfoEx.photoPath.dwSize] = '\0';
+
+			idCerInfoEx.englishName.dwSize = strlen(sIDXData[1]);
+			memcpy(idCerInfoEx.englishName.data, sIDXData[1], idCerInfoEx.englishName.dwSize);
+			idCerInfoEx.englishName.data[idCerInfoEx.englishName.dwSize] = '\0';
+
+			idCerInfoEx.nationality.dwSize = strlen(sIDXData[4]);
+			memcpy(idCerInfoEx.nationality.data, sIDXData[4], idCerInfoEx.nationality.dwSize);
+			idCerInfoEx.nationality.data[idCerInfoEx.nationality.dwSize] = '\0';
+
+			idCerInfoEx.idVersion.dwSize = strlen(sIDXData[9]);
+			memcpy(idCerInfoEx.idVersion.data, sIDXData[9], idCerInfoEx.idVersion.dwSize);
+			idCerInfoEx.idVersion.data[idCerInfoEx.idVersion.dwSize] = '\0';
+
+			idCerInfoEx.idType.dwSize = strlen("I");
+			memcpy(idCerInfoEx.idType.data, "I", idCerInfoEx.idType.dwSize);
+			idCerInfoEx.idType.data[idCerInfoEx.idType.dwSize] = '\0';
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "IDCerGetDataEx",
+				"%s", idCerInfoEx.idType.data);
+			idCerInfoEx.reserved.dwSize = 0;
+			memset(idCerInfoEx.reserved.data, 0, IDCER_EIGHT_BYTE_SIZE);
+		}
+		else if (atoi(sIDXData[0]) == 3)
+		{
+			
+			idCerInfoEx.name.dwSize = strlen(sIDXData[1]);
+			memcpy(idCerInfoEx.name.data, sIDXData[1], idCerInfoEx.name.dwSize);
+			idCerInfoEx.name.data[idCerInfoEx.name.dwSize] = '\0';
+
+			idCerInfoEx.sex.dwSize = strlen(sIDXData[2]);
+			memcpy(idCerInfoEx.sex.data, sIDXData[2], idCerInfoEx.sex.dwSize);
+			idCerInfoEx.sex.data[idCerInfoEx.sex.dwSize] = '\0';
+
+			//处理生日日期
+			string str(sIDXData[4]);
+			str.insert(4, "年");
+			str.insert(6 + strlen("年"), "月");
+			str.insert(str.size(), "日");
+
+			char p[32] = { 0 };
+			strcpy(p, str.c_str());
+			idCerInfoEx.birthday.dwSize = strlen(p);
+			memcpy(idCerInfoEx.birthday.data, p, idCerInfoEx.birthday.dwSize);
+			idCerInfoEx.birthday.data[idCerInfoEx.birthday.dwSize] = '\0';
+
+			idCerInfoEx.address.dwSize = strlen(sIDXData[5]);
+			memcpy(idCerInfoEx.address.data, sIDXData[5], idCerInfoEx.address.dwSize);
+			idCerInfoEx.address.data[idCerInfoEx.address.dwSize] = '\0';
+
+			idCerInfoEx.newAddress.dwSize = 0;
+			memset(idCerInfoEx.newAddress.data, 0, MAX_IDCER_INFO_SIZE);
+			idCerInfoEx.newAddress.data[idCerInfoEx.newAddress.dwSize] = '\0';
+
+			idCerInfoEx.idno.dwSize = strlen(sIDXData[6]);
+			memcpy(idCerInfoEx.idno.data, sIDXData[6], idCerInfoEx.idno.dwSize);
+			idCerInfoEx.idno.data[idCerInfoEx.idno.dwSize] = '\0';
+
+			idCerInfoEx.department.dwSize = strlen(sIDXData[7]);
+			memcpy(idCerInfoEx.department.data, sIDXData[7], idCerInfoEx.department.dwSize);
+			idCerInfoEx.department.data[idCerInfoEx.department.dwSize] = '\0';
+
+			memcpy(szExpireStart, sIDXData[8], 8);
+			memcpy(szExpireEnd, sIDXData[8] + 9, 8);
+			g_pGvar.AddCharToDate(szExpireStart, '.');
+			if (strcmp(szExpireEnd, "长期") != NULL)
+			{
+				g_pGvar.AddCharToDate(szExpireEnd, '.');
+			}
+			idCerInfoEx.startDate.dwSize = strlen(szExpireStart);
+			memcpy(idCerInfoEx.startDate.data, szExpireStart, idCerInfoEx.startDate.dwSize);
+			idCerInfoEx.startDate.data[idCerInfoEx.startDate.dwSize] = '\0';
+
+			idCerInfoEx.endDate.dwSize = strlen(szExpireEnd);
+			memcpy(idCerInfoEx.endDate.data, szExpireEnd, idCerInfoEx.endDate.dwSize);
+			idCerInfoEx.endDate.data[idCerInfoEx.endDate.dwSize] = '\0';
+
+			idCerInfoEx.photoPath.dwSize = strlen(sIDXData[14]);
+			memcpy(idCerInfoEx.photoPath.data, sIDXData[14], idCerInfoEx.photoPath.dwSize);
+			idCerInfoEx.photoPath.data[idCerInfoEx.photoPath.dwSize] = '\0';
+
+			idCerInfoEx.idType.dwSize = strlen("J");
+			memcpy(idCerInfoEx.idType.data, "J", idCerInfoEx.idType.dwSize);
+			idCerInfoEx.idType.data[idCerInfoEx.idType.dwSize] = '\0';
+
+			idCerInfoEx.txzCode.dwSize = strlen(sIDXData[9]);
+			memcpy(idCerInfoEx.txzCode.data, sIDXData[9], idCerInfoEx.txzCode.dwSize);
+			idCerInfoEx.txzCode.data[idCerInfoEx.txzCode.dwSize] = '\0';
+
+			idCerInfoEx.issuedSN.dwSize = strlen(sIDXData[10]);
+			memcpy(idCerInfoEx.issuedSN.data, sIDXData[10], idCerInfoEx.issuedSN.dwSize);
+			idCerInfoEx.issuedSN.data[idCerInfoEx.issuedSN.dwSize] = '\0';
+
+		}
+		
+		throw Error_Succeed;
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+        /*if (sIDXData != NULL)
+	g_pGvar.FreeArryBuf((void **)sIDXData, MID_LEN);
+	if (sDevStatus != NULL)
+        g_pGvar.FreeArryBuf((void **)sDevStatus, MIN_LEN);*/
+	return eRet;
+}
+
+
+ ErrorCodeEnum IDCardReaderNantian::IDCerGetData(IDCerInfo& idCerInfo)
+{
+	ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(IDCerGetData)
+
+	memset(&idCerInfo, 0, sizeof(IDCerInfo));
+	char szDllPath[1024] = { 0 };
+	char szHeadPath[1024] = { 0 };
+	int iCardType = 0;
+	char *sIDXData[MID_LEN];
+	int idxFlag = 0;
+	char *sDevStatus[MIN_LEN];
+	try
+	{
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevOpen",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+		//查询设备状态
+		for (int i = 0; i < MIN_LEN; i++)
+		{
+			sDevStatus[i] = new char[MID_LEN];
+			memset(sDevStatus[i], 0, MID_LEN);
+		}
+		iRet = g_pGvar.m_pDRVObj->GetDevStatus(idxFlag, sDevStatus);
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetDataEx",
+				"GetDeviceStatus error return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "device is offline, code:%d", iRet);
+			throw Error_Hardware;
+		}
+		else
+		{
+			if (atoi(sDevStatus[2]) != IDCARDREADER_MEDIAPRESENT)
+			{
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetDataEx",
+					"no card in device");
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				strcpy(g_pGvar.m_errMsg, "no card in device");
+				throw Error_DevMedia;
+			}
+		}
+		for (size_t i = 0; i < MID_LEN; i++)
+		{
+			sIDXData[i] = new char[MAX_LEN];
+			memset(sIDXData[i], 0, MAX_LEN);
+		}			
+		iRet = g_pGvar.m_pDRVObj->ReadIDXData(sIDXData);
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetDataEx",
+				"ReadAllIDInfo error,return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "read card error, code:%d", iRet);
+			throw Error_Hardware;
+		}
+
+	
+		if (strstr(sIDXData[3], "族"))
+		{
+			int len = strlen(sIDXData[3]);
+			idCerInfo.nation.dwSize = strlen(sIDXData[3]) - (strlen("族"));
+			memcpy(idCerInfo.nation.data, sIDXData[3], idCerInfo.nation.dwSize);
+			idCerInfo.nation.data[idCerInfo.nation.dwSize] = '\0';
+		}
+		else
+		{
+			idCerInfo.nation.dwSize = strlen(sIDXData[3]);
+			memcpy(idCerInfo.nation.data, sIDXData[3], idCerInfo.nation.dwSize);
+			idCerInfo.nation.data[idCerInfo.nation.dwSize] = '\0';
+		}
+		//20200324 by qhw
+		//如果民族超过56个名族代码,则直接返回代码
+		char sTmpCode[1024] = { 0 };
+		g_pGvar.SwitchNationToCode(idCerInfo.nation.data, sTmpCode);
+		if (strlen(sTmpCode) > 0)
+		{
+			idCerInfo.nation.dwSize = strlen(sTmpCode);
+			memcpy(idCerInfo.nation.data, sTmpCode, idCerInfo.nation.dwSize);
+			idCerInfo.nation.data[idCerInfo.nation.dwSize] = '\0';
+		}
+
+		idCerInfo.name.dwSize = strlen(sIDXData[1]);
+		memcpy(idCerInfo.name.data, sIDXData[1], idCerInfo.name.dwSize);
+		idCerInfo.name.data[idCerInfo.name.dwSize] = '\0';
+
+		idCerInfo.idno.dwSize = strlen(sIDXData[6]);
+		memcpy(idCerInfo.idno.data, sIDXData[6], idCerInfo.idno.dwSize);
+		idCerInfo.idno.data[idCerInfo.idno.dwSize] = '\0';
+
+		idCerInfo.sex.dwSize = strlen(sIDXData[2]);
+		memcpy(idCerInfo.sex.data, sIDXData[2], idCerInfo.sex.dwSize);
+		idCerInfo.sex.data[idCerInfo.sex.dwSize] = '\0';
+
+		//处理生日日期
+		string str(sIDXData[4]);
+		str.insert(4, "年");
+		str.insert(6 + strlen("年"), "月");
+		str.insert(str.size(), "日");
+		g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetData",
+			"1");
+		char p[32] = { 0 };
+		strcpy(p, str.c_str());
+		idCerInfo.birthday.dwSize = strlen(p);
+		memcpy(idCerInfo.birthday.data, p, idCerInfo.birthday.dwSize);
+		idCerInfo.birthday.data[idCerInfo.birthday.dwSize] = '\0';
+
+		idCerInfo.address.dwSize = strlen(sIDXData[5]);
+		memcpy(idCerInfo.address.data, sIDXData[5], idCerInfo.address.dwSize);
+		idCerInfo.address.data[idCerInfo.address.dwSize] = '\0';
+
+		idCerInfo.newAddress.dwSize = 0;
+		memset(idCerInfo.newAddress.data, 0, MAX_IDCER_INFO_SIZE);
+		idCerInfo.newAddress.data[idCerInfo.newAddress.dwSize] = '\0';
+
+		idCerInfo.department.dwSize = strlen(sIDXData[7]);
+		memcpy(idCerInfo.department.data, sIDXData[7], idCerInfo.department.dwSize);
+		idCerInfo.department.data[idCerInfo.department.dwSize] = '\0';
+
+		char szExpireStart[16] = { 0 };
+		char szExpireEnd[16] = { 0 };
+		memcpy(szExpireStart, sIDXData[8], strlen(sIDXData[8]));
+		memcpy(szExpireEnd, sIDXData[9], strlen(sIDXData[9]));
+		g_pGvar.AddCharToDate(szExpireStart, '.');
+		if (strcmp(szExpireEnd, "长期") != NULL)
+		{
+			g_pGvar.AddCharToDate(szExpireEnd, '.');
+		}
+
+		idCerInfo.startDate.dwSize = strlen(szExpireStart);
+		memcpy(idCerInfo.startDate.data, szExpireStart, idCerInfo.startDate.dwSize);
+		idCerInfo.startDate.data[idCerInfo.startDate.dwSize] = '\0';
+
+		idCerInfo.endDate.dwSize = strlen(szExpireEnd);
+		memcpy(idCerInfo.endDate.data, szExpireEnd, idCerInfo.endDate.dwSize);
+		idCerInfo.endDate.data[idCerInfo.endDate.dwSize] = '\0';
+
+		idCerInfo.photoPath.dwSize = strlen(sIDXData[13]);
+		memcpy(idCerInfo.photoPath.data, sIDXData[13], idCerInfo.photoPath.dwSize);
+		idCerInfo.photoPath.data[idCerInfo.photoPath.dwSize] = '\0';
+
+		throw Error_Succeed;
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+        /*if (sDevStatus != NULL)
+	g_pGvar.FreeArryBuf((void **)sDevStatus, MIN_LEN);
+	if (sIDXData != NULL)
+        g_pGvar.FreeArryBuf((void **)sIDXData, MID_LEN);*/
+	return eRet;
+}
+
+ ErrorCodeEnum IDCardReaderNantian::ForceIDEject()
+{
+	ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(ForceIDEject)
+	
+	int idxFlag = 0;
+	char *sDevStatus[MIN_LEN];
+
+	try
+	{
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevOpen",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+
+		//查询设备状态,是否存在卡
+		for (int i = 0; i < MIN_LEN; i++)
+		{
+			sDevStatus[i] = new char[MID_LEN];
+			memset(sDevStatus[i], 0, MID_LEN);
+		}
+		iRet = g_pGvar.m_pDRVObj->GetDevStatus(idxFlag, sDevStatus);
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetDataEx",
+				"GetDeviceStatus error return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "device is offline, code:%d", iRet);
+			throw Error_Hardware;
+		}
+		else
+		{
+			if (atoi(sDevStatus[1]) == IDCARDREADER_DEVBUSY)
+			{
+				//设备正在读卡或扫描,不能进行退卡
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_DEBUG, "ForceIDEject",
+					"dev is busy error return:%d", Error_DevMedia);
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				strcpy(g_pGvar.m_errMsg, "device is busy");
+				throw Error_DevMedia;
+			}
+			//三个传感器均未检测到卡
+			if (atoi(sDevStatus[2]) == IDCARDREADER_MEDIANOTPRESENT)
+            {   
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_DEBUG, "ForceIDEject",
+					"dev no media return:%d", Error_DevMedia);
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				strcpy(g_pGvar.m_errMsg, "no card in device");
+				throw Error_DevMedia;
+			}
+		}
+		
+		iRet = g_pGvar.m_pDRVObj->EjectCard();
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR,
+					"ForceIDEject",
+					"resetsoft and eject error,return:%d", iRet);
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				sprintf(g_pGvar.m_errMsg, "force eject card error, code:%d", iRet);
+				throw Error_Hardware;
+			
+		}
+		throw Error_Succeed;
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+        //if (sDevStatus != NULL)
+        //g_pGvar.FreeArryBuf((void **)sDevStatus, MIN_LEN);
+	return eRet;
+}
+
+void* thread( void *arg )
+{ 
+       g_pGvar.TheardEnd = true;
+	int iRet = 0;
+	while (1)
+	{
+		if (g_pGvar.m_bIsCancel)
+		{
+			g_pGvar.g_flag = false;
+			break;
+		}
+		//检查是否放入卡
+                iRet = g_pGvar.m_pDRVObj->InsertCard(NULL);
+ 		g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_DEBUG, "ThreadInsertCard",
+ 			" CheckCardIn return:%d", iRet);
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			//未插入卡,继续等待
+			usleep(150000);
+			continue;
+		}
+		else
+		{
+			g_pGvar.g_flag = false;
+			break;
+		}
+	}
+	g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_DEBUG, "ThreadInsertCard",
+		"InsertCard Thread End");
+g_pGvar.TheardEnd = false;
+	
+    return arg;
+}
+
+ ErrorCodeEnum IDCardReaderNantian::IDCerRFControl(bool bControl)
+{
+	ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(IDCerRFControl)
+	
+	pthread_t th;
+	int arg = 0;
+	int *thread_ret = NULL;
+	char *sDevStatus[MIN_LEN] = {0};		
+	try
+	{
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "DevOpen",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+		//accecpt insert card
+		if (bControl)
+		{
+			g_pGvar.g_flag = true;
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "IDCerRFControl",
+				"bControl is true");
+			g_pGvar.m_bIsCancel = TRUE;
+                        usleep(150000);
+			g_pGvar.m_bIsCancel = FALSE;
+	
+			
+			iRet = pthread_create( &th, NULL, thread, &arg );
+			if( iRet != 0 )
+            {
+				printf( "Create thread error!\n");
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				sprintf(g_pGvar.m_errMsg, "Create thread error, code:%d", iRet);
+				throw Error_Hardware;
+			}
+		}
+		//eject card
+		else
+		{
+			g_pGvar.m_bIsCancel = TRUE;
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "IDCerRFControl","bControl is false");
+				//throw Error_Succeed;
+				//get device status 
+				//查询设备状态
+			for (int i = 0; i < MIN_LEN; i++)
+			{
+				sDevStatus[i] = new char[MID_LEN];
+				memset(sDevStatus[i], 0, MID_LEN);
+			}
+			iRet = g_pGvar.m_pDRVObj->GetDevStatus(0, sDevStatus);
+			if (iRet != E_DRVBASE_SUCCESS)
+			{
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetDataEx",
+					"GetDeviceStatus error return:%d", iRet);
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				sprintf(g_pGvar.m_errMsg, "device is offline, code:%d", iRet);
+				throw Error_Hardware;
+			}
+			else
+			{
+				if (atoi(sDevStatus[2]) != IDCARDREADER_MEDIAPRESENT)
+				{
+					g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetDataEx",
+						"no card in device");
+					memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+					strcpy(g_pGvar.m_errMsg, "no card in device");
+					throw Error_DevMedia;
+				}
+			}
+				
+				iRet = g_pGvar.m_pDRVObj->EjectCard();
+			if (iRet != E_DRVBASE_SUCCESS)
+			{
+					g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR,
+						"ForceIDEject",
+						"resetsoft and eject error,return:%d", iRet);
+					memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+					sprintf(g_pGvar.m_errMsg, "force eject card error, code:%d", iRet);
+					throw Error_Hardware;
+			}
+		}
+			//g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "IDCerRFControl","eject card,return:%d", iRet);
+		
+		throw Error_Succeed;
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+        //if (sDevStatus != NULL)
+        //g_pGvar.FreeArryBuf((void **)sDevStatus, MIN_LEN);
+	return eRet;
+}
+
+ ErrorCodeEnum IDCardReaderNantian::ScanIDAndSaveImage()
+ {
+	 ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(ScanIDAndSaveImage)
+	
+	char *sDevStatus[MIN_LEN] = {0};
+	/*char *picpath[MIN_LEN] = {0};
+	for (int i = 0; i < MIN_LEN; i++)
+		{
+			picpath[i] = new char[MID_LEN];
+			memset(picpath[i], 0, MID_LEN);
+		}*/
+	try
+	{
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "ScanIDAndSaveImage",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+		for (int i = 0; i < MIN_LEN; i++)
+			{
+				sDevStatus[i] = new char[MID_LEN];
+				memset(sDevStatus[i], 0, MID_LEN);
+			}	
+			
+		iRet = g_pGvar.m_pDRVObj->GetDevStatus(0, sDevStatus);
+			if (iRet != E_DRVBASE_SUCCESS)
+			{
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "ScanIDAndSaveImage",
+					"GetDeviceStatus error return:%d", iRet);
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				sprintf(g_pGvar.m_errMsg, "device is offline, code:%d", iRet);
+				throw Error_Hardware;
+			}
+			else
+			{
+				if (atoi(sDevStatus[2]) != IDCARDREADER_MEDIANOTPRESENT)
+				{
+					g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "ScanIDAndSaveImage",
+						"card in device begin eject");
+						iRet = g_pGvar.m_pDRVObj->EjectCard();
+						if (iRet != E_DRVBASE_SUCCESS)
+						{
+								g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR,
+									"ScanIDAndSaveImage",
+									"resetsoft and eject error,return:%d", iRet);
+								memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+								sprintf(g_pGvar.m_errMsg, "force eject card error, code:%d", iRet);
+								throw Error_Hardware;
+						}
+					
+				}
+			}
+        g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_INFO, "ScanIDAndSaveImage",
+				"Call Dev ScanIDAndSaveImage");
+		iRet = g_pGvar.m_pDRVObj->ScanIDXPic(NULL);
+		if (iRet != E_DRVBASE_SUCCESS)
+			{
+				g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "ScanIDAndSaveImage",
+					"ScanIDXPic error return:%d", iRet);
+				memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+				sprintf(g_pGvar.m_errMsg, "ScanIDXPic error return:%d", iRet);
+				throw Error_Hardware;
+			}
+		
+		throw Error_Succeed;
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+        //g_pGvar.FreeArryBuf((void **)picpath, MID_LEN);
+	
+	return eRet;
+	 
+ }
+
+ErrorCodeEnum IDCardReaderNantian::QueryCardPos(int& pos)
+{
+	ErrorCodeEnum eRet = Error_Succeed;
+	int iRet = 0;
+	_AUTOTRACE_(QueryCardPos)
+	
+	int idxFlag = 0;
+	char *sDevStatus[MIN_LEN];
+
+	try
+	{
+		if (g_pGvar.m_pDRVObj == NULL)
+		{
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			strcpy(g_pGvar.m_errMsg, "Load library error");
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "QueryCardPos",
+				"Load library error");
+			throw Error_DevLoadFileFailed;
+		}
+        
+        if(g_pGvar.TheardEnd)
+        {
+            pos = 0;
+            throw Error_Succeed;
+        }
+		//查询设备状态,是否存在卡
+		for (int i = 0; i < MIN_LEN; i++)
+		{
+			sDevStatus[i] = new char[MID_LEN];
+			memset(sDevStatus[i], 0, MID_LEN);
+		}
+		iRet = g_pGvar.m_pDRVObj->GetDevStatus(idxFlag, sDevStatus);
+		if (iRet != E_DRVBASE_SUCCESS)
+		{
+			g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "IDCerGetDataEx",
+				"GetDeviceStatus error return:%d", iRet);
+			memset(g_pGvar.m_errMsg, 0, MAX_LEN);
+			sprintf(g_pGvar.m_errMsg, "device is offline, code:%d", iRet);
+			throw Error_Hardware;
+		}
+		else
+		{
+			if (atoi(sDevStatus[2]) == IDCARDREADER_MEDIANOTPRESENT)
+			{
+				pos = 0;
+                                g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "QueryCardPos","MEDIANOTPRESENT");
+			}
+			if (atoi(sDevStatus[2]) == IDCARDREADER_MEDIAENTERING)
+			{
+				pos = 2;
+                                g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "QueryCardPos","MEDIAENTERING");
+			}
+			if (atoi(sDevStatus[2]) == IDCARDREADER_MEDIAPRESENT)
+			{
+				pos = 1;
+                                g_pGvar.m_pTrace->WriteTrace(CILIXTRACE_L_ERROR, "QueryCardPos","MEDIAPRESENT");
+			}
+		}
+		throw Error_Succeed;
+	}
+	catch (ErrorCodeEnum errcode)
+	{
+		eRet = errcode;
+	}
+        //if (sDevStatus != NULL)
+        //g_pGvar.FreeArryBuf((void **)sDevStatus, MIN_LEN);
+	return eRet;
+}
+
+
+
+
+

+ 50 - 0
DevAdapter/nantian/idcer.1.1/idcertificate.nantian.1.1.h

@@ -0,0 +1,50 @@
+// 下列 ifdef 块是创建使从 DLL 导出更简单的
+// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 XFSIDCIDCARDREADER310_EXPORTS
+// 符号编译的。在使用此 DLL 的
+// 任何项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
+// XFSIDCIDCARDREADER310_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
+// 符号视为是被导出的。
+
+#ifndef __IDCERTIFICATE_H__
+#define __IDCERTIFICATE_H__
+#include "GVar.h"
+
+#define IDCERTIFICATE_API  __attribute__((visibility("default")))
+
+class IDCardReaderNantian : public IDCerClass
+{
+public:
+	IDCardReaderNantian();
+	~IDCardReaderNantian();
+
+	virtual ErrorCodeEnum DevOpen(DWORD dwPort);
+	virtual ErrorCodeEnum IDCerRFControl(bool bControl);
+	virtual ErrorCodeEnum IDCerAuthenticate();
+	virtual ErrorCodeEnum IDCerGetData(IDCerInfo & idCerInfo);
+	virtual ErrorCodeEnum IDCerGetDataEx(IDCerInfoEx & idCerInfoEx);
+	virtual ErrorCodeEnum ForceIDEject();
+	virtual ErrorCodeEnum ScanIDAndSaveImage();
+	virtual ErrorCodeEnum QueryCardPos(int &pos);
+	virtual ErrorCodeEnum GetDevCategory(DevCategoryInfo & devCategory);
+	virtual ErrorCodeEnum Reset();
+	virtual ErrorCodeEnum DevClose();
+	virtual ErrorCodeEnum GetLastErr(DevErrorInfo &devErrInfo);
+};
+/*
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(push,1)
+
+	IDCERTIFICATE_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass *&baseObj);
+	IDCERTIFICATE_API ErrorCodeEnum ReleaseDevComponent(DeviceBaseClass *&pBaseObj);
+
+#pragma pack(pop)
+
+#ifdef __cplusplus
+}
+#endif*/
+
+#endif
+

+ 1861 - 0
DevAdapter/nantian/pinpad.1.1/CILIX_AUX_UTILS.h

@@ -0,0 +1,1861 @@
+/*************************************************************************
+  > File Name: CILIX_AUX_UTILS.h
+  > Author: 陈必灏
+  > Mail: chenbh@nantian.com.cn
+  > Created Time: 2017年09月21日 星期四 09时43分04秒
+ ************************************************************************/
+
+#ifndef _CILIX_AUX_UTILS_H
+#define _CILIX_AUX_UTILS_H
+
+
+#include<stdio.h>
+#include<stdlib.h>      
+#include<unistd.h>    
+#include<sys/types.h>   
+#include<sys/stat.h>     
+#include<fcntl.h>       
+#include<termios.h>   
+#include<errno.h>
+#include<dirent.h>
+#include<string>
+#include<string.h>
+#include<sys/time.h>
+#include<time.h>
+#include<stdarg.h>
+#include<map>
+#include<vector>
+#include<iostream>
+#include<list>
+#include<memory.h>
+#include<malloc.h>
+#include<wchar.h>
+#include<dlfcn.h>
+#include <ostream>
+#include <fstream>
+
+using namespace std;
+
+typedef char* LPSTR;
+typedef unsigned long ULONG;
+typedef int BOOL;
+#define TRUE 1
+#define FALSE 0
+
+typedef vector<string> STRVECTOR;
+typedef string::size_type STRPOS;
+
+typedef struct _cilix_sys_time_ {
+	int Year;
+	int Month;
+	int Day;
+	int DayOfWeek;
+	int DayOfYear;
+	int Hour;
+	int Minute;
+	int Second;
+	int MilliSecond;
+} CILIX_SYS_TIME, *LP_CILIX_SYS_TIME;
+
+class CILIX_AUX_X
+{
+
+	public:
+
+		static int CILIX_strlen_00(char* pSrc)
+		{
+			if (!pSrc)  return 0;
+
+			int x=0;
+			for (; pSrc[x]||pSrc[x+1]; x++);
+
+			return (x+2);
+		}	
+		static int CILIX_strlen_00_w(wchar_t* pSrc)
+		{
+			if (!pSrc) return 0;
+
+			int x=0;
+			for (; pSrc[x]||pSrc[x+1]; x++);
+			return (x+2);
+		}
+		static void GetLocalTime(CILIX_SYS_TIME *pt)
+		{
+			struct timeval ttv;
+			gettimeofday(&ttv,NULL);
+			struct tm* ttm = localtime(&ttv.tv_sec);
+
+			pt->Year = ttm->tm_year+1900;
+			pt->Month = ttm->tm_mon+1;
+			pt->Day = ttm->tm_mday;
+			pt->DayOfWeek = ttm->tm_wday;
+			pt->DayOfYear = ttm->tm_yday+1;
+			pt->Hour = ttm->tm_hour;
+			pt->Minute = ttm->tm_min;
+			pt->Second = ttm->tm_sec;
+			pt->MilliSecond = (int)(ttv.tv_usec/1000);
+		}
+		static void Sleep(int ms)
+		{
+			usleep(ms*1000);
+		}
+		static int Tickcount()
+		{
+			struct timeval tv;
+			gettimeofday(&tv,NULL);
+			return (tv.tv_sec*1000 + tv.tv_usec/1000);
+		}
+		static void CILIX_uti_unpack(unsigned char *pSrc,unsigned char* pDest,int len)
+		{    
+			unsigned char ch1, ch2;
+			int i ;
+			for(  i = 0; i < len; i++ )
+			{
+				ch1 = (pSrc[i] & 0xF0) >> 4;
+				ch2 = pSrc[i] & 0x0F;
+				ch1 += ( (ch1 > 9 ) ? 0x37 : 0x30 );
+				ch2 += ( (ch2 > 9 ) ? 0x37 : 0x30 );
+				pDest[i*2] = ch1;
+				pDest[i*2 + 1] = ch2;
+			}
+		}
+
+		static void CILIX_uti_pack(unsigned char* pSrc,unsigned char* pDest,int len)
+		{
+			char  ch1, ch2;
+			int i;
+			for(  i = 0; i < (len / 2); i++ )
+			{
+				ch1 = pSrc[i*2];
+				ch2 = pSrc[i*2 + 1];
+				(ch1 >= 'a' && ch1 <= 'z') ? (ch1 -= 32) : (ch1);
+				(ch2 >= 'a' && ch2 <= 'z') ? (ch2 -= 32) : (ch2);
+				ch1 -= ( (ch1 > '9' ) ? 0x37 : 0x30 );
+				ch2 -= ( (ch2 > '9' ) ? 0x37 : 0x30 );
+				pDest[i] = ( ch1 << 4 ) | ch2;
+			}
+		}
+		static char* CILIX_GetModuleCurPath(char* sCurPath)
+		{
+			std::string wdir;
+			Dl_info dl_info;
+			dladdr((void*)CILIX_GetModuleCurPath, &dl_info);
+			std::string path(dl_info.dli_fname);
+			wdir = path.substr(0, path.find_last_of('/') + 1);
+
+			strcpy(sCurPath, wdir.c_str());
+			return  sCurPath;
+		}
+		static bool CreateDirectory(char* path)
+		{
+			int i = 0;
+			char FilePath[100] = "";
+			FilePath[0] = path[0];
+			for(i= 1; i<=strlen(path); i++)
+			{
+				FilePath[i] = path[i];
+				if(path[i] == '/')
+				{
+					char tempBuff[1024]= "";
+					memcpy(tempBuff,FilePath,i);
+
+					int iRet =  access(tempBuff,F_OK);
+
+					if(access(tempBuff, F_OK) != 0)
+					{  
+						mkdir(FilePath,S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IRWXO);
+					}
+				}
+			}
+			return true;
+		}
+		static int CILIX_split_str(string strSrc,STRVECTOR& vecDest,char cSep)
+		{
+			STRPOS pos = 0;
+			STRPOS prev_pos  = 0;
+			while((pos = strSrc.find_first_of(cSep,pos))!= string::npos)
+			{
+				string strTemp = strSrc.substr(prev_pos,pos-prev_pos);
+				vecDest.push_back(strTemp);
+				prev_pos = ++ pos;
+			}
+
+			if(!strSrc.empty())
+				vecDest.push_back(&strSrc[prev_pos]);
+
+			return vecDest.size();
+		}
+		static int CILIX_split_str_00(char* sSrc,STRVECTOR& vecDest)
+		{
+			if(!sSrc || (!sSrc[0]&& !sSrc[1]))return 0;
+
+			do
+			{
+				vecDest.push_back(sSrc);
+				sSrc += strlen(sSrc)+1;
+			}while(sSrc[0]);
+			return vecDest.size();
+		} 
+
+		static bool CILIX_X_SetINIKeyString(char* fileName,char* title,char* key , char* KeyValue)
+		{
+			if((fileName == NULL)||(title == NULL)||
+					(key == NULL)||(KeyValue == NULL)) return FALSE;
+
+			FILE *frp = NULL;
+			char szLine[1024*10],szRcvData[1024*10];
+			memset(szLine,0,sizeof(szLine));
+			memset(szRcvData,0,sizeof(szRcvData));
+
+			int rtnval = 0,iDataLen = 0,iRcvDataLen = 0;
+			frp = fopen(fileName,"r");
+			if(frp == NULL)return FALSE;
+
+			while(!feof(frp))
+			{
+				rtnval = fgetc(frp);
+				szLine[iDataLen++] = rtnval;
+
+				if(rtnval == EOF) break;
+			}
+
+			fclose(frp);
+			//    printf("...%d...",iDataLen);
+			//   printf("%s",szLine);
+			//iDataLen = data + enter + \n + EOF 
+			char sztitle[1024];
+			memset(sztitle,0,sizeof(sztitle));
+			strcpy(sztitle,"[");
+			strcat(sztitle,title);
+			strcat(sztitle,"]");
+			//   printf("%s",sztitle);
+			char szkey[1024];
+			memset(szkey,0,sizeof(szkey));
+			strcpy(szkey,key);
+			strcat(szkey,"=");
+
+			char* titlePostion  = NULL;
+			if((titlePostion = strstr(szLine,sztitle))== NULL) return FALSE;
+
+			int ititlePostion = titlePostion - szLine;
+			// printf("...%d...",ititlePostion);
+			char* keyPostion = NULL;
+			if((keyPostion = strstr(szLine+ititlePostion,szkey)) == NULL) return FALSE;
+			int ikeyPostion = keyPostion - szLine;
+			// printf("***%d***",ikeyPostion);
+			int iStarPostion = ikeyPostion+strlen(szkey);
+
+			char* endPostion = NULL;
+			if((endPostion = strchr(szLine+iStarPostion,'\r'))!= NULL);
+			else if((endPostion = strchr(szLine+iStarPostion,'\n'))!= NULL);
+			else return FALSE;
+			int iendPostion = endPostion - szLine;
+			// printf("+++%d+++",iendPostion);
+
+			memcpy(szRcvData,szLine,iStarPostion);
+
+			iRcvDataLen += iStarPostion;
+
+			//        char keyData[100]= "384000";
+
+			memcpy(szRcvData+iStarPostion,KeyValue,strlen(KeyValue));
+			iRcvDataLen += strlen(KeyValue);
+
+			memcpy(szRcvData+iStarPostion+strlen(KeyValue),szLine+iendPostion,iDataLen-iendPostion);
+			iRcvDataLen += (iDataLen-iendPostion);
+			// printf("%s",szRcvData);
+
+
+			// printf("...%d...",iRcvDataLen);
+			FILE  *fwp = NULL;
+			fwp = fopen(fileName,"w+");
+			if(fwp == NULL)
+			{
+				//   printf("Open error\n");
+				return FALSE;
+			}
+
+			int iWriteNum = fwrite(szRcvData,sizeof(char),iRcvDataLen-1,fwp);
+			fclose(fwp);
+			if(iWriteNum == 0)
+			{
+				// printf("Write error \n");
+				return FALSE;
+			}
+
+
+			// printf("...%d...",iWriteNum);
+
+			return TRUE;
+		}
+		static  bool CILIX_X_INIKeyString(char* fileName , char* title,char* key,char* KeyValue,char* Default =NULL )
+		{ 
+			if((fileName == NULL)||(title == NULL)||
+					(key == NULL)||(KeyValue == NULL))
+				return FALSE;
+
+			FILE *fp = NULL ;
+			char szLine[1024],tmpstr[1024];
+			char *tmp = NULL;
+
+			memset(szLine,0,sizeof(szLine));
+			memset(tmpstr,0,sizeof(tmpstr));
+			int rtnval, i = 0,flag = 0;
+
+			fp = fopen(fileName,"r");
+			if(fp == NULL)  return FALSE;   
+
+			while(!feof(fp))
+			{
+				rtnval = fgetc(fp);
+				if(rtnval == EOF)break;
+				else szLine[i++] = rtnval;
+
+				if(rtnval == '\n') 
+				{
+					szLine[--i] = '\0';        
+					i = 0;
+					tmp = strchr(szLine,'=');                    
+					if((tmp != NULL)&&(flag == 1))
+					{
+						if (strstr(szLine,key)!= NULL)
+						{
+							if('#'== szLine[0]);
+							else if('\/'== szLine[0]&& '\/' == szLine[1]);
+							else
+							{
+								strcpy(tmpstr,tmp+1);
+								fclose(fp);
+
+								char* FindPos = NULL;
+								if((FindPos = strchr(tmpstr,'\n'))!= NULL)
+								{
+									memcpy(KeyValue,tmpstr,FindPos-tmpstr);
+								}
+								else if((FindPos =strchr(tmpstr,'\r'))!=NULL)
+									memcpy(KeyValue,tmpstr,FindPos-tmpstr);
+								else strcpy(KeyValue,tmpstr);
+
+								return TRUE;
+							}                                       
+						}
+					}
+					else
+					{
+						strcpy(tmpstr,"[");          
+						strcat(tmpstr,title);
+						strcat(tmpstr,"]");    
+						if(strncmp(tmpstr,szLine,strlen(tmpstr)) == 0)
+							flag  = 1;
+					}
+				}
+
+			}
+
+			fclose(fp);
+			if(Default == NULL) return FALSE;
+			strcpy(KeyValue,Default);
+			return TRUE;
+		}
+
+		static char* strupr(char *str)
+		{
+			char *ptr = str;
+			while (*ptr != '\0') {
+				if (islower(*ptr))
+					*ptr = toupper(*ptr);
+				ptr++;
+			}
+			return str;
+		}
+		static char* strlwr(char* str)
+		{
+			char* ptr = str;
+			while (*ptr != '\0') {
+				if (isupper(*ptr))
+					*ptr = tolower(*ptr);
+				ptr++;
+			}
+			return str;
+		}
+		static void TraceVAS(int hService, ULONG id, const char* f, char* p_szTraceData, ...)
+		{
+
+			char f_trace_data[1024 * 10 + 1] = "";
+			if (p_szTraceData != NULL)
+			{
+				va_list f_va_list;
+				va_start(f_va_list, p_szTraceData);
+				vsprintf(f_trace_data + strlen(f_trace_data), p_szTraceData, f_va_list);
+				va_end(f_va_list);
+			}
+			fprintf(stderr, "$$$$$$$$$$$$$$ %s H:<%d> ID:<%d> [%s] -- %s\n", __TIME__, hService, id, f, f_trace_data);
+		}
+
+};
+//?ַ???\C0\A9չ??
+class CAU_unpacker
+{
+	public:
+
+		CAU_unpacker(const char* s) : str_(0)
+	{
+		unpack(s, ( s ? strlen(s) : 0 ));
+	}
+		CAU_unpacker(const char* s, int l) : str_(0)
+	{
+		unpack(s, l);
+	}
+
+		~CAU_unpacker()
+		{
+			free(this->str_);
+		}
+
+		char* str()
+		{
+			return this->str_;
+		}
+		int len()
+		{
+			return this->len_;
+		}
+
+	private:
+		void unpack(const char* s, int l)
+		{
+			free(this->str_);
+			this->str_ = NULL;
+			//
+			unsigned char* s_unpack_ = (unsigned char*)malloc(l*2 + 10);
+			memset(s_unpack_, 0, l*2 + 10);
+			CILIX_AUX_X::CILIX_uti_unpack((unsigned char*)s, s_unpack_, l);
+			//
+			this->str_ = (char*)s_unpack_;
+			this->len_ = l*2;
+		}
+
+	private:
+		char* str_;
+		int len_;
+};
+//???ַ????Զ?\C0\A9չ??
+class CAU_unpacker_w
+{
+	public:
+
+		CAU_unpacker_w(const wchar_t* s) : str_(0)
+	{
+		unpack(s, ( s ? wcslen(s) : 0 ));
+	}
+		CAU_unpacker_w(const wchar_t* s, int l) : str_(0)
+	{
+		unpack(s, l);
+	}
+
+		~CAU_unpacker_w()
+		{
+			free(this->str_);
+		}
+
+		char* str()
+		{
+			return this->str_;
+		}
+		int len()
+		{
+			return this->len_;
+		}
+
+	private:
+		void unpack(const wchar_t* s, int l)
+		{
+			free(this->str_);
+			this->str_ = NULL;
+			//
+			unsigned char* s_unpack_ = (unsigned char*)malloc(l*sizeof(wchar_t)*2 + 10);
+			memset(s_unpack_, 0, l*sizeof(wchar_t)*2 + 10);
+			CILIX_AUX_X::CILIX_uti_unpack((unsigned char*)s, s_unpack_, l*sizeof(wchar_t));
+			//
+			this->str_ = (char*)s_unpack_;
+			this->len_ = l*sizeof(wchar_t)*2;
+		}
+
+	private:
+		char* str_;
+		int len_;
+};
+//?ַ????Զ?ѹ????
+class CAU_packer
+{
+	public:
+
+		CAU_packer(const char* s) : str_(0)
+	{
+		pack(s, ( s ? strlen(s) : 0 ));
+	}
+		CAU_packer(const char* s, int l) : str_(0)
+	{
+		pack(s, l);
+	}
+
+		~CAU_packer()
+		{
+			free(this->str_);
+		}
+
+		char* str()
+		{
+			return this->str_;
+		}
+		int len()
+		{
+			return this->len_;
+		}
+
+	private:
+		void pack(const char* s, int l)
+		{
+			free(this->str_);
+			this->str_ = NULL;
+			//
+			unsigned char* s_pack_ = (unsigned char*)malloc(l/2 + 10);
+			memset(s_pack_, 0, l/2 + 10);
+			CILIX_AUX_X::CILIX_uti_pack((unsigned char*)s, s_pack_, l);
+			//
+			this->str_ = (char*)s_pack_;
+			this->len_ = l/2;
+		}
+
+	private:
+		char* str_;
+		int len_;
+};
+typedef int (*CILIXTTY_READINISH)(char*,int);
+class CILIX_TTY_Op
+{
+	public:
+		CILIX_TTY_Op()
+		{
+			this->fd = 0;
+		}
+		~CILIX_TTY_Op()
+		{
+			this->Close();
+		}
+
+		virtual int Open(char* szPort,int nBaudRate)
+		{     
+			this->speed = this->GetBaudRate(nBaudRate);
+			if(this->speed == -1) return -1;
+
+			this->fd = open( szPort, O_RDWR|O_NONBLOCK);  
+			if(this->fd == FALSE) return -1;
+
+			struct termios options;
+			if(tcgetattr(this->fd,&options))
+			{
+				close(this->fd);
+				return -1;
+			}
+
+			options.c_cflag &= ~CSIZE;
+			options.c_cflag |= CS8;
+			options.c_cflag &= ~CSTOPB;
+
+			cfmakeraw(&options);
+			cfsetispeed(&options,this->speed);
+			cfsetospeed(&options,this->speed);
+
+			if(tcsetattr(this->fd,TCSANOW,&options)!= 0)
+			{
+				close(this->fd);
+				return -1;
+			}
+
+			return 0;
+		} 
+
+
+		virtual int Open(char* szPort,int nBaudRate, int nEvent,int cflag )
+		{     
+			this->speed = this->GetBaudRate(nBaudRate);
+			if(this->speed == -1) return -1;
+
+			this->fd = open( szPort, O_RDWR|O_NONBLOCK);  
+			if(this->fd == FALSE) return -1;
+
+			struct termios options;
+			if(tcgetattr(this->fd,&options))
+			{
+				close(this->fd);
+				return -1;
+			}
+
+			cfmakeraw(&options);
+
+			options.c_cflag &= ~CSIZE;
+			options.c_cflag |= CS8;
+			options.c_cflag &= ~CSTOPB;
+
+			//options.c_cflag |= CLOCAL|CREAD;
+			//options.c_oflag &= ~OPOST;
+			//options.c_cc[VTIME] = 0;
+			//options.c_cc[VMIN] = 0; 
+			//tcflush(this->fd,TCOFLUSH);
+			//if(cflag == 0 ) options.c_cflag &= ~CRTSCTS;
+			//else options.c_cflag |= CRTSCTS;
+
+			switch (nEvent) 
+			{   
+				case 'n':
+				case 'N':    
+					options.c_cflag &= ~PARENB;   /* Clear parity enable */
+					options.c_iflag &= ~INPCK;     /* Enable parity checking */ 
+					break;  
+				case 'o':   
+				case 'O':     
+					options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/  
+					options.c_iflag |= INPCK;             /* Disnable parity checking */ 
+					break;  
+				case 'e':  
+				case 'E':   
+					options.c_cflag |= PARENB;     /* Enable parity */    
+					options.c_cflag &= ~PARODD;   /* 转换为偶效验*/     
+					options.c_iflag |= INPCK;       /* Disnable parity checking */
+					break;
+				case 'S': 
+				case 's':  /*as no parity*/   
+					options.c_cflag &= ~PARENB;
+					options.c_cflag &= ~CSTOPB;
+					break;  
+				default:   
+					fprintf(stderr,"Unsupported parity\n");    
+					return -1;  
+			}
+
+			cfsetispeed(&options,this->speed);
+			cfsetospeed(&options,this->speed);
+
+			if(tcsetattr(this->fd,TCSANOW,&options)!= 0)
+			{
+				close(this->fd);
+				return -1;
+			}
+
+			tcflush(this->fd,TCIOFLUSH);
+
+			return 0;
+		} 
+
+		virtual int Close()
+		{
+			if(this->fd > 0) 
+				close(this->fd);
+
+			return 0;
+		}
+		virtual int Write(char* szSend,int nSendLen,int InnerTime)
+		{
+			if(this->fd == -1) return -1;
+
+			int iLen = 0;
+
+			tcflush(this->fd,TCIFLUSH);
+
+			iLen = write(this->fd,szSend,nSendLen);
+			if(iLen < nSendLen)
+			{
+				//clear buff
+				tcflush(this->fd,TCOFLUSH);
+				return -1;
+			}
+			return iLen;
+		}
+		virtual int Read(char* szRecvData,int nRcvlen,int inner,int total,int isleep,CILIXTTY_READINISH srf)
+		{
+			int ret_ = 0,count_ = 0 ;
+			char buff_[2];
+
+			int time_old = CILIX_AUX_X::Tickcount(),time_last = 0;
+
+			while((CILIX_AUX_X::Tickcount() -time_old ) < total)
+			{
+				memset(buff_,0,sizeof(buff_));
+				ret_ = read(this->fd,buff_,1);
+
+				if(ret_ != 1)
+				{
+					if(count_ > 0)
+					{
+						if((CILIX_AUX_X::Tickcount() - time_last) >= inner) break;
+					}
+
+					if(isleep > 0)  CILIX_AUX_X::Sleep(isleep);
+
+				}
+				else if(ret_ == 1)
+				{
+					memcpy(szRecvData+count_,buff_,1);
+					count_++;
+
+					if(count_ >= nRcvlen) break;
+
+					//get data full
+					if(srf != NULL && srf(szRecvData,count_)) break;
+
+					time_last = CILIX_AUX_X::Tickcount();        
+				}
+				//  else return ret_;
+			}
+			/*if(count_ == 0) printf("Read Count 0 :%s\n",strerror(errno));*/
+			return count_;
+		}
+		virtual int Read(char* szRecvData ,int nRcvlen,int inner ,int total,int isleep)
+		{
+			int iRet = 0,ret_ = 0;
+			struct timeval time_old,time_last,time_now;
+
+			gettimeofday(&time_old,NULL);
+
+			time_last.tv_sec = 0;
+			time_last.tv_usec = 0;
+			time_now.tv_sec = 0;
+			time_now.tv_usec = 0;
+
+			long _old = time_old.tv_sec * 1000 + time_old.tv_usec /1000;
+			long _time = 0, _now = 0;
+
+			while((_time - _old) < total)
+			{
+				unsigned char buf_;
+				ret_ = read(this->fd,&buf_,1);
+
+				if(ret_ != 1) 
+				{
+					if(iRet > 0)
+					{
+						gettimeofday(&time_now,NULL);
+						_now = time_now.tv_sec * 1000 + time_now.tv_usec /1000;
+						if((_now - _time) >= inner ) break;
+					}
+					if(isleep > 0)usleep(isleep*1000);
+
+				}
+				if(ret_ == 1) 
+				{
+					szRecvData[iRet]= buf_;
+					iRet ++ ;
+
+					if(iRet >= nRcvlen) break;
+
+					gettimeofday(&time_last,NULL);
+					_time = time_last.tv_sec * 1000 + time_last.tv_usec/1000;
+				}
+
+			}
+			return iRet;
+		}
+	private:
+		int fd;
+		speed_t speed;
+		static speed_t GetBaudRate(int iBaudRate)
+		{
+			switch(iBaudRate)
+			{
+				case 0:     return B0;
+				case 9600:  return B9600;
+				case 19200: return B19200;
+				case 38400: return B38400;
+				case 115200:return B115200;
+				case 57600: return B57600;
+				default: return -1;        
+			}
+		}
+};
+
+//日志级别
+#define CILIXTRACE_L_DEBUG			1
+#define CILIXTRACE_L_INFO			2
+#define CILIXTRACE_L_WARN			3
+#define CILIXTRACE_L_ERROR			4
+#define CILIXTRACE_L_FATAL			5
+#define CILIXTRACE_L_SYSTEM	     	9
+
+class CILIXTrace
+{
+	public:
+		CILIXTrace(char* p_szDir,char* p_szMethodName,char* p_szFilePrefix):day_(0),month_(0),year_(0)
+	{
+		char szPath[1024],iniPath[1024];
+		memset(szPath,0,sizeof(szPath));
+
+		CILIX_AUX_X::CILIX_GetModuleCurPath(szPath);
+		memset(iniPath,0,sizeof(iniPath));
+		strcat(iniPath,szPath);
+		strcat(iniPath,"CILIX_CONFIG.ini");
+
+		//是否记录日志
+		char dtFlag[200] = ""; 
+		CILIX_AUX_X::CILIX_X_INIKeyString(iniPath,"DEVTRACE","Switch",dtFlag,"1");
+		atoi(dtFlag) ? m_trace_flag = TRUE:m_trace_flag = FALSE;
+
+		//是否日志加密
+		char dtcrypt[200] = "";
+		CILIX_AUX_X::CILIX_X_INIKeyString(iniPath,"DEVTRACE","Encrypt",dtcrypt,"0");
+		atoi(dtcrypt) ? m_trace_crypt = TRUE :m_trace_crypt = FALSE;
+
+		//文件保留天数
+		char dtRD[200] = "";
+		CILIX_AUX_X::CILIX_X_INIKeyString(iniPath,"DEVTRACE","FileDay",dtRD,"30");
+		m_file_reserve_days = atoi(dtRD);
+
+		// m_file_open_mode="a+";
+		strcpy(m_file_open_mode,"a+");
+
+		memset(m_file_prefix_,0,sizeof(m_file_prefix_));
+		strcpy(m_file_prefix_ ,p_szFilePrefix);
+
+		//日志级别
+		char dtLevel[200]= "";
+		CILIX_AUX_X::CILIX_X_INIKeyString(iniPath,"DEVTRACE","Level",dtLevel,"INFO");
+		m_trace_level = this->l_a2i(dtLevel);
+
+		if(m_trace_flag == FALSE) return ;
+
+		//日志路径
+		char dtTracePath[1024];
+		memset(dtTracePath,0,sizeof(dtTracePath));
+		CILIX_AUX_X::CILIX_X_INIKeyString(iniPath,"DEVTRACE","Path",dtTracePath,"/etc/UFS/CILIXTrace");
+
+		//创建日文件夹
+		//CILIX_AUX_X::CreateDirectory(dtTracePath);
+
+		//创建日志文件夹
+		mkdir(dtTracePath,S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IRWXO);
+
+		memset(m_dir_,0,sizeof(m_dir_));
+		strcpy(m_dir_, dtTracePath);	
+
+		//文件名
+		memset(m_ModuleName,0,sizeof(m_ModuleName));
+		strcpy(m_ModuleName, p_szMethodName);
+		
+		CILIX_SYS_TIME  p;
+		CILIX_AUX_X::GetLocalTime(&p);
+		
+		this->WriteTrace(CILIXTRACE_L_SYSTEM,"===","|*********************************************|");
+		this->WriteTrace(CILIXTRACE_L_SYSTEM,"===","      START  %04d-%02d-%2d %02d-%02d-%02d      ",
+				p.Year,p.Month,p.Day,p.Hour,p.Minute,p.Second);
+
+	}
+		virtual ~CILIXTrace()
+		{
+	
+		CILIX_SYS_TIME  p;
+		CILIX_AUX_X::GetLocalTime(&p);
+	
+		this->WriteTrace(CILIXTRACE_L_SYSTEM,"===","       END  %04d-%02d-%2d %02d-%02d-%02d       ",
+				p.Year,p.Month,p.Day,p.Hour,p.Minute,p.Second);
+		this->WriteTrace(CILIXTRACE_L_SYSTEM,"===","|*********************************************|");
+		}
+
+		void WriteTrace(const char* p_szMethodName,const char* p_szTraceData,...)
+		{  
+			if(m_trace_flag == FALSE ) return;
+
+			char f_trace_data[1024 * 10+1] = "";
+
+			if(p_szTraceData != NULL)
+			{
+				va_list f_va_list;
+				va_start (f_va_list,p_szTraceData);
+				vsprintf(f_trace_data+strlen(f_trace_data),p_szTraceData,f_va_list);
+				va_end(f_va_list);
+			}
+			this->write_trace(CILIXTRACE_L_INFO,p_szMethodName,f_trace_data);
+		}
+		void WriteTrace(int p_iLevel, const char* p_szMethodName,const char* p_szTraceData,...)
+		{
+			if(m_trace_flag == FALSE ) return;
+
+			//判断日志级别
+			if(p_iLevel < m_trace_level) return ;
+
+			char f_trace_data[1024 * 10+1] = "";
+			if(p_szTraceData != NULL)
+			{
+				va_list f_va_list;
+				va_start (f_va_list,p_szTraceData);
+				vsprintf(f_trace_data+strlen(f_trace_data),p_szTraceData,f_va_list);
+				va_end(f_va_list);
+			}
+			this->write_trace(p_iLevel,p_szMethodName,f_trace_data);
+		}
+
+	private:
+		//Write file Mode
+		void write_trace(int p_iLevel, const char* p_szMethodName ,const char* p_szTraceData)
+		{
+			char f_trace_data[1024*10 +1] = "";
+
+			//trace level
+			char f_sl[200] = "";
+			this->l_i2a(p_iLevel, f_sl);
+
+			//time
+			/*
+			   time_t timep = time(NULL);
+			   struct tm* p = localtime(&timep);*/
+			CILIX_SYS_TIME  p;
+			CILIX_AUX_X::GetLocalTime(&p);
+			
+			//生成日期信息
+			sprintf(f_trace_data,"%04d-%02d-%02d %02d:%02d:%02d:%03d [%s] <%s> - ",
+					p.Year,p.Month,p.Day,
+					p.Hour,p.Minute,p.Second,p.MilliSecond,f_sl,(p_szMethodName == NULL ?"":p_szMethodName));
+
+			if(year_ != p.Year || month_ != p.Month || day_ != p.Day)
+			{
+				char sPath[1025] = "\0";
+				//创建日期目录
+				sprintf(sPath,"%s/%04d%02d%02d",m_dir_,p.Year,p.Month,p.Day);
+				mkdir(sPath,S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IRWXO);
+				
+				sprintf(m_dir_,"%s/%s",sPath,m_ModuleName);
+				mkdir(m_dir_,S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IRWXO);
+			}
+			
+			//trace info
+			if(p_szTraceData != NULL)
+				strcat(f_trace_data,p_szTraceData);
+
+			strcat(f_trace_data,"\r\n");
+
+			int f_i_trace_data_len = strlen(f_trace_data);
+
+			if(m_trace_crypt == TRUE)
+			{
+				int i ; 
+				for(i = 0; i< f_i_trace_data_len; f_trace_data[i++]^=0x55);
+			}
+
+			char f_szFileName[1030] = "";
+			sprintf(f_szFileName,"%s/",m_dir_);
+
+			sprintf(f_szFileName+strlen(f_szFileName), "%s_%d%d%d.txt",
+					m_file_prefix_,
+					p.Year,
+					p.Month,
+					p.Day);
+
+			//open file Write 
+			FILE *f_pFile = NULL;
+			if((f_pFile = fopen(f_szFileName,m_file_open_mode))!= NULL)
+			{
+				fseek(f_pFile,0L,SEEK_END);
+				fwrite(f_trace_data,sizeof(char),f_i_trace_data_len,f_pFile);
+				fclose(f_pFile);
+			}
+			//判断是否产生新的一天
+			if(year_ != p.Year || month_ != p.Month || day_ != p.Day)
+			{
+				this->delete_redun_files();
+				this->year_ = p.Year;
+				this->month_ = p.Month;
+				this->day_ = p.Day;
+			}
+		}
+		//
+		int l_a2i(char* sl)
+		{
+			int il = CILIXTRACE_L_INFO;
+			{
+				if (!strcmp(sl, "DEBUG"))	il = CILIXTRACE_L_DEBUG;
+				if (!strcmp(sl, "INFO"))	il = CILIXTRACE_L_INFO;
+				if (!strcmp(sl, "WARN"))	il = CILIXTRACE_L_WARN;
+				if (!strcmp(sl, "ERROR"))	il = CILIXTRACE_L_ERROR;
+				if (!strcmp(sl, "FATAL"))	il = CILIXTRACE_L_FATAL;
+				if (!strcmp(sl, "SYSTEM"))	il = CILIXTRACE_L_SYSTEM;
+			}
+			return il;
+		}
+		void l_i2a(int il, char* sl)
+		{
+			strcpy(sl, "UNKNOWN");
+			if (il == CILIXTRACE_L_DEBUG) strcpy(sl, "DEBUG");
+			if (il == CILIXTRACE_L_INFO) strcpy(sl, "INFO");
+			if (il == CILIXTRACE_L_WARN) strcpy(sl, "WARN");
+			if (il == CILIXTRACE_L_ERROR) strcpy(sl, "ERROR");
+			if (il == CILIXTRACE_L_FATAL) strcpy(sl, "FATAL");
+			if (il == CILIXTRACE_L_SYSTEM) strcpy(sl, "SYSTEM");
+		}
+	private:
+
+		//根据文件保留天数,删除过期文件
+		void delete_redun_files()
+		{
+			//如果不记录日志则返回
+			if(!m_trace_flag)
+				return ;
+
+			char szPath[1025] = "\0";
+			char iniPath[1025] = "\0";
+			CILIX_AUX_X::CILIX_GetModuleCurPath(szPath);
+			memset(iniPath,0,sizeof(iniPath));
+			strcat(iniPath,szPath);
+			strcat(iniPath,"CILIX_CONFIG.ini");
+
+			char dtTracePath[1024];
+			memset(dtTracePath,0,sizeof(dtTracePath));
+			CILIX_AUX_X::CILIX_X_INIKeyString(iniPath,"DEVTRACE","Path",dtTracePath,"");
+
+			//fprintf(stderr,"m_dir_%s\n ",dtTracePath);
+			REMOVE_FILES(dtTracePath);
+		}
+		void DeleteFolder(string dirIn)
+		{
+			if(dirIn.empty())return ;
+
+			struct stat s;
+			stat(dirIn.c_str(),&s);
+			if(!S_ISDIR(s.st_mode))return ;
+
+			DIR* open_dir = opendir(dirIn.c_str());
+			if(!open_dir) return ;
+
+			dirent* pDren = NULL;
+			while((pDren = readdir(open_dir)) != NULL)
+			{
+				string fileName = pDren->d_name;
+
+				if(fileName == "."||fileName == "..")
+					continue;
+
+				struct stat st;
+				string name = dirIn+string("/")+fileName;
+
+				stat(name.c_str(),&st);
+
+				if(S_ISDIR(st.st_mode))
+				{
+					DeleteFolder(name);
+
+					remove(name.c_str());
+				}
+				else if(S_ISREG(st.st_mode))
+					remove(name.c_str());
+
+			}
+			closedir(open_dir);
+
+		}
+
+		BOOL REMOVE_FILES(string dirIn)
+		{
+			//搜索到的文件夹个数
+			int f_iFileNumber = 0;
+			//搜索到的文件名列表,最多1024 个文件
+			char *f_szFileNames[1025] = {0};
+
+			if(dirIn.empty())return FALSE;
+
+			struct stat s;
+			stat(dirIn.c_str(),&s);
+			if(!S_ISDIR(s.st_mode))return FALSE;
+
+			DIR* open_dir = opendir(dirIn.c_str());
+			if(!open_dir) return FALSE;
+
+			dirent* pDren = NULL;
+			while((pDren = readdir(open_dir)) != NULL)
+			{
+				string fileName = pDren->d_name;
+
+				if(fileName == "."||fileName == "..")
+					continue;
+
+				struct stat st;
+				string name = dirIn+string("/")+fileName;
+
+				stat(name.c_str(),&st);
+
+				if(S_ISDIR(st.st_mode))
+				{
+
+					f_szFileNames[f_iFileNumber] = (char*)malloc(strlen(name.c_str())+1);
+					strcpy(f_szFileNames[f_iFileNumber],name.c_str());
+
+					f_iFileNumber++;
+				}
+			}
+			closedir(open_dir);
+
+			qsort(f_szFileNames,f_iFileNumber,sizeof(char*),cmpfile_names);
+
+			for(int f_iFNTemp = f_iFileNumber;m_file_reserve_days>0 && f_iFNTemp >m_file_reserve_days;f_iFNTemp--)
+			{
+				//	cout<<f_szFileNames[f_iFNTemp-1]<<endl;
+				DeleteFolder(f_szFileNames[f_iFNTemp-1]);
+				remove(f_szFileNames[f_iFNTemp-1]);
+			}
+
+			for(int i = 0;i<f_iFileNumber;i++)
+				free(f_szFileNames[i]);
+			return TRUE;
+		}
+		static int cmpfile_names(const void* p_pFileName1,const void* p_pFileName2)
+		{
+			return strcmp(*(char**)p_pFileName2,*(char**)p_pFileName1);
+		}
+
+	private:
+		//trace dir
+		char m_dir_[1030];
+		//trace prefix
+		char m_file_prefix_[200];
+		//trace Name
+		char m_ModuleName[100] ;
+		//open mode
+		char m_file_open_mode[100];
+		//data
+		int m_file_reserve_days;
+		//trace flag
+		bool m_trace_flag;
+		//trace crypt
+		bool m_trace_crypt;
+		//level
+		int m_trace_level;
+
+	private:
+		int day_;
+		int month_;
+		int year_;
+};
+//Auto
+class CILIXAutoTrace
+{
+	public:
+		CILIXAutoTrace(CILIXTrace* pt,char *method ,int* iret):m_pt(pt),m_iret(iret)
+	{
+		memset(m_method,0,sizeof(m_method));
+		strcpy(m_method,method);
+		m_pt->WriteTrace(m_method,"Entry");
+	}
+		~CILIXAutoTrace()
+		{
+			m_pt->WriteTrace(m_method,"Exit - [iret = %d]",*m_iret);
+		}
+	private:
+		CILIXTrace *m_pt;
+		char m_method[1025];
+		int* m_iret;
+};
+class CILIX_X_Config
+{
+	public:
+	private:
+		char sCfgPath[1025];
+};
+
+typedef list<void*> VPLIST,*LPVPLIST;
+typedef VPLIST::iterator VPLISTIT;
+
+typedef map<void*,LPVPLIST> VPLIST_MAP;
+typedef VPLIST_MAP::iterator VPLIST_MAP_IT;
+
+class CILIX_Allocator
+{
+	public:
+		CILIX_Allocator()
+		{
+
+		}
+		virtual ~CILIX_Allocator()
+		{
+			FreeBuffer();
+		}
+	public:
+		int AllocateBuffer(unsigned long iSize,void** pData)
+		{
+			if(iSize == 0)
+			{
+				*pData = NULL;
+				return 0;
+			}
+			void *mem = malloc(iSize);
+			if(mem == NULL) return -1;
+
+			memset(mem,0,iSize);
+			LPVPLIST vl = new VPLIST;
+			vl->insert(vl->end(),mem);
+			VM.insert(VPLIST_MAP::value_type(mem,vl));
+			*pData = mem;
+			return 0;
+		}
+		int AllocateMore(unsigned long iSize,void* pOriginal,void ** pData)
+		{
+			if(iSize == 0) 
+			{
+				*pData = NULL;
+				return 0;
+			}
+			VPLIST_MAP_IT it_ = VM.find(pOriginal);
+			if(it_ == VM.end()) return -1;
+
+			void *mem = malloc(iSize);
+			if(mem == NULL) return -1;
+
+			memset(mem,0,iSize);
+			(it_->second)->insert((it_->second)->end(),mem);
+			*pData = mem;
+			return 0;
+		}
+		void FreeBuffer(void* pOriginal)
+		{
+			if(pOriginal == NULL) return ;
+
+			VPLIST_MAP_IT it_ = VM.find(pOriginal);
+			if(it_ != VM.end())
+			{
+				LPVPLIST vl = it_->second;
+
+				VPLISTIT t= vl->begin();
+				for(t;t!=vl->end();)
+				{
+					free(*t);
+					vl->erase(t++);
+				}
+				delete vl;
+				VM.erase(it_);
+			}
+
+		}
+	private:
+		void FreeBuffer()
+		{
+			//遍历VM中的元素
+			while(!VM.empty())
+			{
+				VPLIST_MAP_IT it_ = VM.begin();
+				LPVPLIST vl = it_->second;
+
+				//遍列地址列表
+				VPLISTIT t = vl->begin();
+				for(t;t!=vl->end();)
+				{
+					free(*t);
+					vl->erase(t++);
+				}
+				delete vl;
+				VM.erase(it_);
+			}
+		}
+	private:
+		//存放各个LPVPLIST对象的MAP
+		VPLIST_MAP VM;
+
+};
+
+
+///////////////////////////////////#####未使用STL的字符串处理集合#####///////////////////////////////////
+
+/***********************************************
+  说明:
+  空白字符包括:
+  空格:				0x20
+  换页符		(\f):	0x0c
+  换行符		(\n):	0x0a
+  回车符		(\r):	0x0d
+  制表符		(\t):	0x09
+  垂直制表符	(\v):	0x0b
+ ************************************************/
+
+class CPlusStringProcess
+{
+	public:
+		//构造器
+		CPlusStringProcess()
+		{
+			//空白字符合集
+			memset(m_pWhiteChar, 0, sizeof(m_pWhiteChar));
+			strcpy(m_pWhiteChar, "\x20\x0c\x0a\x0d\x09\x0b");
+		}
+
+	public:
+		//功能:去除左边的空白符
+		//参数:p_pStrOld	: 要操作的字符串
+		//		p_pStrNew	: 如果为null则修改作用于p_pStrOld,否则通过p_pStrNew返回
+		//备注:如果p_pStrOld为空指针或空字符串,则不对原字符串做任何修改,同时如果p_pStrNew
+		//		也不为空,则将p_pStrNew置为一个空字符串
+		void TrimLeft(char* p_pStrOld, char* p_pStrNew = NULL)
+		{
+			//如果操作字符串为空则直接返回
+			if (p_pStrOld == NULL || strlen(p_pStrOld) <= 0)
+			{
+				if (p_pStrNew != NULL)
+					p_pStrNew[0] = '\0';
+				return;
+			}
+			//临时存储字符串
+			char* f_pTempStr = (char*)malloc(sizeof(char)*(strlen(p_pStrOld)+1));
+			memset(f_pTempStr, 0, sizeof(char)*(strlen(p_pStrOld)+1));
+			//查找左边第一个非空白符
+			char* f_pStrIdx = p_pStrOld;
+			for (unsigned int i=0; i<strlen(p_pStrOld)&&is_white_char_(*f_pStrIdx); f_pStrIdx++,i++);
+			//拷贝不包括左边空白字符的字符串到f_pTempStr
+			strcpy(f_pTempStr, f_pStrIdx);
+			//产生输出
+			if (p_pStrNew == NULL)
+				strcpy(p_pStrOld, f_pTempStr);
+			else
+				strcpy(p_pStrNew, f_pTempStr);
+			//释放临时字符串空间
+			free(f_pTempStr);
+		}
+
+		//功能:去除右边的空白符
+		//参数:p_pStrOld	: 要操作的字符串
+		//		p_pStrNew	: 如果为null则修改作用于p_pStrOld,否则通过p_pStrNew返回
+		//备注:如果p_pStrOld为空指针或空字符串,则不对原字符串做任何修改,同时如果p_pStrNew
+		//		也不为空,则将p_pStrNew置为一个空字符串
+		void TrimRight(char* p_pStrOld, char* p_pStrNew = NULL)
+		{
+			//如果操作字符串为空则直接返回
+			if (p_pStrOld == NULL || strlen(p_pStrOld) <= 0)
+			{
+				if (p_pStrNew != NULL)
+					p_pStrNew[0] = '\0';
+				return;
+			}
+			//临时存储字符串
+			char* f_pTempStr = (char*)malloc(sizeof(char)*(strlen(p_pStrOld)+1));
+			memset(f_pTempStr, 0, sizeof(char)*(strlen(p_pStrOld)+1));
+			//拷贝原操作字符串
+			strcpy(f_pTempStr, p_pStrOld);
+			//循环去除右边的空白符
+			for (int i=strlen(f_pTempStr)-1; i>=0&&is_white_char_(f_pTempStr[i]); f_pTempStr[i--]='\0');
+			//产生输出
+			if (p_pStrNew == NULL)
+				strcpy(p_pStrOld, f_pTempStr);
+			else
+				strcpy(p_pStrNew, f_pTempStr);
+			//释放临时字符串空间
+			free(f_pTempStr);
+		}
+
+		//功能:去除左右两边的空白符
+		//参数:p_pStrOld	: 要操作的字符串
+		//		p_pStrNew	: 如果为null则修改作用于p_pStrOld,否则通过p_pStrNew返回
+		//备注:如果p_pStrOld为空指针或空字符串,则不对原字符串做任何修改,同时如果p_pStrNew
+		//		也不为空,则将p_pStrNew置为一个空字符串
+		void TrimLR(char* p_pStrOld, char* p_pStrNew = NULL)
+		{
+			//如果操作字符串为空则直接返回
+			if (p_pStrOld == NULL || strlen(p_pStrOld) <= 0)
+			{
+				if (p_pStrNew != NULL)
+					p_pStrNew[0] = '\0';
+				return;
+			}
+			//临时存储字符串
+			char* f_pTempStr = (char*)malloc(sizeof(char)*(strlen(p_pStrOld)+1));
+			memset(f_pTempStr, 0, sizeof(char)*(strlen(p_pStrOld)+1));
+			//拷贝原操作字符串
+			strcpy(f_pTempStr, p_pStrOld);
+			//去除左边空格
+			TrimLeft(f_pTempStr);
+			//去除右边空格
+			TrimRight(f_pTempStr);
+			//产生输出
+			if (p_pStrNew == NULL)
+				strcpy(p_pStrOld, f_pTempStr);
+			else
+				strcpy(p_pStrNew, f_pTempStr);
+			//释放临时字符串空间
+			free(f_pTempStr);
+		}
+
+		//功能:去除字符串里的所有空白符
+		//参数:p_pStrOld	: 要操作的字符串
+		//		p_pStrNew	: 如果为null则修改作用于p_pStrOld,否则通过p_pStrNew返回
+		//备注:如果p_pStrOld为空指针或空字符串,则不对原字符串做任何修改,同时如果p_pStrNew
+		//		也不为空,则将p_pStrNew置为一个空字符串
+		void TrimAll(char* p_pStrOld, char* p_pStrNew = NULL)
+		{
+			//如果操作字符串为空则直接返回
+			if (p_pStrOld == NULL || strlen(p_pStrOld) <= 0)
+			{
+				if (p_pStrNew != NULL)
+					p_pStrNew[0] = '\0';
+				return;
+			}
+			//临时存储字符串
+			char* f_pTempStr = (char*)malloc(sizeof(char)*(strlen(p_pStrOld)+1));
+			memset(f_pTempStr, 0, sizeof(char)*(strlen(p_pStrOld)+1));
+			//拷贝非空白字符
+			int f_iIdx = 0;
+			for (unsigned int i=0; i<strlen(p_pStrOld); i++)
+				if (!is_white_char_(p_pStrOld[i]))
+					f_pTempStr[f_iIdx++] = p_pStrOld[i];
+			//产生输出
+			if (p_pStrNew == NULL)
+				strcpy(p_pStrOld, f_pTempStr);
+			else
+				strcpy(p_pStrNew, f_pTempStr);
+			//释放临时字符串空间
+			free(f_pTempStr);
+		}
+
+		//功能:分隔字符串
+		//参数:p_pStrOld	: 要操作的字符串
+		//		p_pSpliter	: 分隔字符串
+		//		p_ppResult	: 指针数组,保存分割后的各个字符串地址
+		//备注:1. 如果p_pStrOld为空指针或空字符串,则不会产生任何输出
+		//		2. 如果p_pSpliter为空指针或空字符串,则不会产生任何输出
+		//		3. 指针数组p_ppResult指向分割后的各字符串指针,以NULL结束,
+		//		   因此如果分割得到n个字符串则该数组大小应为n+1
+		//		4. 指针数组p_ppResult应由外部保证传入时已将所有元素初始化为NULL
+		//		5. p_ppResult各元素所指向的内存数据需要调用FreeSplitOut方法来释放,
+		//		   将p_ppResult[0]指针值传给FreeSplitOut函数即可完成释放
+		//		6. 假设用"A"来分割字符串"12A34A",则分割后应得到"12"/"34"/"",
+		//		   但因为最后一个字符串是空字符串,所以最终返回的只有"12"/"34",
+		//		   有如"12AA",最后得到的字符串也只有"12"
+		void Split(char* p_pStrOld, char* p_pSpliter, char* p_ppResult[])
+		{
+			//如果p_pStrOld为空指针或空字符串则直接返回
+			if (p_pStrOld == NULL || strlen(p_pStrOld) <= 0)
+				return;
+			//如果p_pSpliter为空指针或空字符串则直接返回
+			if (p_pSpliter == NULL || strlen(p_pSpliter) <= 0)
+				return;
+			//操作字符串长度
+			unsigned int f_uiStrOldLen = strlen(p_pStrOld);
+			//分隔字符串长度
+			unsigned int f_uiSpliterLen = strlen(p_pSpliter);
+			//输出字符串,分隔开的各字符串统一存储在该连续的空间上,而由不同的字符串指针来标识
+			char* f_pOutStr = (char*)malloc(sizeof(char)*(f_uiStrOldLen*2));
+			memset(f_pOutStr, 0, sizeof(char)*(f_uiStrOldLen*2));
+			//当前已填充到f_pOutStr的索引值
+			int f_iOutStrIdx = 0;
+			//已分隔开的字符串个数
+			int f_iResultNum = 0;
+			//已查找过的字符串下标索引值
+			int f_iStrOldIdx = 0;
+			//循环查找p_pSpliter出现位置
+			for (char* p=NULL; ((unsigned int)f_iStrOldIdx)<f_uiStrOldLen;)
+			{
+				//新分隔开的字符串长度
+				unsigned int f_uiNewStrLen = 0;
+				//查找下一个分隔字符串
+				p = strstr(p_pStrOld+f_iStrOldIdx, p_pSpliter);
+				//如果没找到分隔字符串说明剩余的全部都需要拷贝
+				if (p == NULL)	
+					f_uiNewStrLen = strlen(p_pStrOld+f_iStrOldIdx);
+				//如果找到分隔字符串说明只拷贝间隔部分
+				else			
+					f_uiNewStrLen = p - (p_pStrOld+f_iStrOldIdx);
+				//拷贝的前提是不为空字符串
+				if (f_uiNewStrLen > 0)
+				{
+					//记录第n个分隔开的字符串指针地址
+					p_ppResult[f_iResultNum++] = f_pOutStr+f_iOutStrIdx;
+					//拷贝第n个分隔开的字符串
+					memcpy(f_pOutStr+f_iOutStrIdx, p_pStrOld+f_iStrOldIdx, f_uiNewStrLen);
+					//更新输出字符串连续地址的索引值,注意需要多向后移一位以保证有'\0'存在
+					f_iOutStrIdx += (f_uiNewStrLen+1);
+				}
+				//更新下一次查找的起始位置
+				f_iStrOldIdx += (f_uiNewStrLen+(p==NULL?0:f_uiSpliterLen));
+			}
+			//如果没有产生输出,则要将f_pOutStr释放,否则由外部来进行释放
+			if (p_ppResult[0] == NULL)
+				free(f_pOutStr);
+		}
+
+		//功能:分隔字符串,该字符串以0x00分隔以两个0x00结束
+		//参数:p_pStrOld		: 要操作的字符串
+		//		p_ppResult		: 指针数组,保存分割后的各个字符串地址
+		//		p_iStrOldMaxLen	: 要操作的字符串最大可能长度,默认为10k
+		//备注:1. 指针数组p_ppResult指向分割后的各字符串指针,以NULL结束,
+		//		   因此如果分割得到n个字符串则该数组大小应为n+1
+		//		2. 指针数组p_ppResult应由外部保证传入时已将所有元素初始化为NULL
+		//		3. p_ppResult各元素所指向的内存数据需要调用FreeSplitOut方法来释放,
+		//		   将p_ppResult[0]指针值传给FreeSplitOut函数即可完成释放
+		//返回:分隔后的串数
+		int Split_00(char* p_pStrOld, char* p_ppResult[], int p_iStrOldMaxLen = 1024*10)
+		{
+			//输出字符串,分隔开的各字符串统一存储在该连续的空间上,而由不同的字符串指针来标识
+			char* f_pOutStr = (char*)malloc(sizeof(char)*(p_iStrOldMaxLen*2));
+			memset(f_pOutStr, 0, sizeof(char)*(p_iStrOldMaxLen*2));
+			//已查找过的字符串下标索引值
+			int f_iStrOldIdx = 0;
+			//当前已填充到f_pOutStr的索引值
+			int f_iOutStrIdx = 0;
+			//新分隔开的字符串长度
+			unsigned int f_uiNewStrLen = 0;
+			//已分隔开的字符串个数
+			int f_iResultNum = 0;
+			//循环获取各字符串
+			for	(	;
+					( p_pStrOld != NULL )	&&
+					( f_iStrOldIdx == 0
+					  ? !( *(p_pStrOld+f_iStrOldIdx) == NULL && *(p_pStrOld+f_iStrOldIdx+1) == NULL )
+					  : 1 )				&&
+					( f_iStrOldIdx != 0
+					  ? !( *(p_pStrOld+f_iStrOldIdx) == NULL ) 
+					  : 1 )				&&
+					( f_uiNewStrLen = strlen(p_pStrOld+f_iStrOldIdx), 1 )
+					;
+					( f_uiNewStrLen > 0 
+					  ? ( p_ppResult[f_iResultNum++] = f_pOutStr+f_iOutStrIdx ,
+						  memcpy(f_pOutStr+f_iOutStrIdx, p_pStrOld+f_iStrOldIdx, f_uiNewStrLen) ,
+						  f_iOutStrIdx += (f_uiNewStrLen+1) ,
+						  f_iStrOldIdx += (f_uiNewStrLen+1) )
+					  : ( f_iStrOldIdx += (f_uiNewStrLen+1) )
+					)
+				);
+			//如果没有产生输出,则要将f_pOutStr释放,否则由外部来进行释放
+			if (p_ppResult == NULL || p_ppResult[0] == NULL)
+				free(f_pOutStr);
+			//返回
+			return f_iResultNum;
+		}
+
+		//功能:分隔Unicode字符串,该字符串以0x0000分隔以两个0x0000结束
+		//参数:p_pStrOld		: 要操作的Unicode字符串
+		//		p_ppResult		: 指针数组,保存分割后的各个Unicode字符串地址
+		//		p_iStrOldMaxLen	: 要操作的Unicode字符串最大可能长度,默认为10k
+		//备注:1. 指针数组p_ppResult指向分割后的Unicode各字符串指针,以NULL结束,
+		//		   因此如果分割得到n个Unicode字符串则该数组大小应为n+1
+		//		2. 指针数组p_ppResult应由外部保证传入时已将所有元素初始化为NULL
+		//		3. p_ppResult各元素所指向的内存数据需要调用FreeSplitOut方法来释放,
+		//		   将p_ppResult[0]指针值传给FreeSplitOut函数即可完成释放
+		//返回:分隔后的串数
+		int SplitW_00(wchar_t* p_pStrOld, wchar_t* p_ppResult[], int p_iStrOldMaxLen = 1024*10)
+		{
+			//输出字符串,分隔开的各字符串统一存储在该连续的空间上,而由不同的字符串指针来标识
+			wchar_t* f_pOutStr = (wchar_t*)malloc(sizeof(wchar_t)*(p_iStrOldMaxLen*2));
+			memset(f_pOutStr, 0, sizeof(wchar_t)*(p_iStrOldMaxLen*2));
+			//已查找过的字符串下标索引值
+			int f_iStrOldIdx = 0;
+			//当前已填充到f_pOutStr的索引值
+			int f_iOutStrIdx = 0;
+			//新分隔开的字符串长度
+			unsigned int f_uiNewStrLen = 0;
+			//已分隔开的字符串个数
+			int f_iResultNum = 0;
+			//循环获取各字符串
+			for	(	;
+					( p_pStrOld != NULL )	&&
+					( f_iStrOldIdx == 0
+					  ? !( *(p_pStrOld+f_iStrOldIdx) == NULL && *(p_pStrOld+f_iStrOldIdx+1) == NULL )
+					  : 1 )				&&
+					( f_iStrOldIdx != 0
+					  ? !( *(p_pStrOld+f_iStrOldIdx) == NULL ) 
+					  : 1 )				&&
+					( f_uiNewStrLen = wcslen(p_pStrOld+f_iStrOldIdx), 1 )
+					;
+					( f_uiNewStrLen > 0 
+					  ? ( p_ppResult[f_iResultNum++] = f_pOutStr+f_iOutStrIdx ,
+						  wmemcpy(f_pOutStr+f_iOutStrIdx, p_pStrOld+f_iStrOldIdx, f_uiNewStrLen) ,
+						  f_iOutStrIdx += (f_uiNewStrLen+1) ,
+						  f_iStrOldIdx += (f_uiNewStrLen+1) )
+					  : ( f_iStrOldIdx += (f_uiNewStrLen+1) )
+					)
+				);
+			//如果没有产生输出,则要将f_pOutStr释放,否则由外部来进行释放
+			if (p_ppResult == NULL || p_ppResult[0] == NULL)
+				free(f_pOutStr);
+			//返回
+			return f_iResultNum;
+		}
+
+		//功能:释放Split/Split_00/SplitW_00方法产生的p_ppResult输出
+		//参数:p_pMem	: 要释放的地址值
+		//备注:调用Split后输出参数为分隔开的各字符串地址,要释放这些字符串
+		//		的内存只需将p_ppResult[0]的值作为参数传入即可完成全部内存的释放,
+		//		另外,释放一个NULL地址值不会出错
+		void FreeSplitOut(void* p_pMem)
+		{
+			free(p_pMem);
+		}
+
+	private:
+		//判断一个字符是否是空白符,为真则返回1,为假则返回0
+		int is_white_char_(char p_cChar)
+		{
+			for (unsigned int i=0; i<strlen(m_pWhiteChar); i++)
+				if (p_cChar == m_pWhiteChar[i])
+					return 1;
+			return 0;
+		}
+
+	private:
+		//空白字符合集
+		char m_pWhiteChar[10];
+};
+
+
+typedef struct __ini_item__
+{
+	string Key;
+	string Value;
+	string Note;
+}INIITEM,*LPINIITEM;
+
+typedef struct __ini_grop__
+{
+	string name;
+	string Note;
+	list<INIITEM> Items;
+}INIGROP,*LPINIGROP;
+
+//INI文件读写
+class UFS_Stream_INI
+{
+	public:
+		//**********
+		//该构造器将读取参数 iniPath 传入的文件信息,来获取INI配置信息,
+		//INI文件编写方式如下
+		//	[NTFKV2CF]
+		//	DeviceDll=libCardReader.so;注释so库名称
+		//  StatusTime=2000;状态轮询时间
+		//	OpenReset=0
+		UFS_Stream_INI(const char* iniPath)
+		{
+			list_name.clear();
+
+			if(!iniPath) return ;
+
+			ifstream fin;
+			fin.open(iniPath);
+			if(fin.fail())return;
+
+			string strBuff = "";
+			string desBuff = "";
+			char tmpChar ;
+			while(!fin.eof())
+			{
+				// 逐行读取并解析
+				strBuff = "";
+				while(!fin.eof())
+				{
+					tmpChar = static_cast<char>(fin.get());
+					if(fin.eof())
+						break;
+					// 如果是换行或者回车则一整行读取完毕 
+					if(tmpChar == static_cast<char>(10) || 
+							tmpChar == static_cast<char>(13) || 
+							tmpChar == static_cast<char>(EOF))
+						break;
+					strBuff += tmpChar;
+				}
+				if(strBuff.length() < 1 || strBuff[0] == note)
+					continue;
+
+				//剔除字符串前后的空格
+				TrimItem(strBuff,desBuff);
+				//cout<<desBuff<<endl;
+				INIGROP ini_grop;
+				ini_grop.name = "";
+				ini_grop.Note = "";
+				ini_grop.Items.clear();
+				//解析键名
+				if(ParseGroup(desBuff,&ini_grop))
+				{
+					list_name.push_back(ini_grop);
+					continue;
+				}
+
+				INIITEM ini_item;
+				ini_item.Key = "";
+				ini_item.Value = "";
+				ini_item.Note = "";
+
+				//解析键值
+				if(ParseItem(desBuff,&ini_item))
+				{
+					list_name.back().Items.push_back(ini_item);
+					continue;
+				}
+			}
+
+			fin.close();
+
+			bFlag = true;
+		}
+		virtual ~UFS_Stream_INI()
+		{
+
+			list_name.clear();
+
+		}
+
+		//功能:数据读取
+		//参数:lpAppName		: 要操作的节名
+		//		lpKeyName		: 要操作的键名
+		//		lpDefault  	 	:如果lpRetrunString为空,则把个变量赋给lpRetrunString
+		//		lpRetrunString 	:存放键值的指针变量,用于接收INI文件中键值(数据)的接收缓冲区
+		//返回值 :
+		//		lpRetrunString数据长度
+		int GetPrivateProfileString(LPSTR lpAppName,LPSTR lpKeyName,LPSTR lpDefault,LPSTR lpRetrunString)
+		{
+			if(!bFlag) return -1;
+			bool bFindFlag = false;
+			//查找组名
+			for(list_name_it = list_name.begin();list_name_it != list_name.end();++list_name_it)
+			{
+				if(!strcmp((char*)lpAppName,(*list_name_it).name.c_str())){
+					bFindFlag = true;
+					break;
+				}
+			}
+			if(!bFindFlag) return -1;
+
+			//cout<<(*list_name_it).name.c_str()<<endl;
+
+			bFindFlag = false;
+			//获取键名键值
+			for(list_item_it = (*list_name_it).Items.begin();
+					list_item_it != (*list_name_it).Items.end();
+					++list_item_it)
+			{
+				//cout<<(*list_item_it).Key<<"++"<<(*list_item_it).Value<<"--"<<(*list_item_it).Note<<endl;
+				if(!strcmp((char*)lpKeyName,(*list_item_it).Key.c_str()))
+				{
+					//cout<<(*list_item_it).Key<<endl;
+					bFindFlag =true;
+					break;
+				}
+			}
+
+			//std::cout<<"name"<<(*list_item_it).Key<<"==>"<<(*list_item_it).Value<<endl;	
+			if(bFindFlag)
+				memcpy(lpRetrunString,(*list_item_it).Value.c_str(),(*list_item_it).Value.length());
+			else
+				memcpy(lpRetrunString,lpDefault,strlen((char*)lpDefault));
+			return strlen((char*)lpRetrunString);
+		}
+	
+		//写文件方式待续。。。
+	
+	private:
+
+		list<INIGROP> list_name;
+		list<INIGROP>::iterator list_name_it;
+		list<INIITEM>::iterator list_item_it;
+		//注释标志
+		char note = ';';
+		bool bFlag = false;
+		//剔除字符串前后的空格
+		static void TrimItem(const string& str,string& dst)
+		{	
+			int ilen = str.length();
+			if(ilen<1)return ;
+
+			//剔除前端的空格
+			int iStart = 0;
+			while(str[iStart] == ' ')
+				++iStart;
+			if(iStart>str.length())
+			{
+				dst = "";
+				return ;
+			}
+
+			int iEnd = ilen;
+			if(iEnd >= str.length())
+				iEnd = str.length();
+
+			//剔除后端的空格
+			while(str[iEnd - 1] == ' ' && iEnd > iStart)
+				--iEnd;
+			// 如果字符串包含在 "" 中则提取出来
+			if(str[iStart] == '\"' && str[iEnd - 1] == '\"')
+			{
+				++iStart;
+				--iEnd;
+			}
+			dst = str.substr(iStart, iEnd - iStart);  
+		}
+
+		//解析分组
+		static bool ParseGroup(const string& str ,LPINIGROP lpIniGrop,char note = ';' )
+		{
+			if(str.empty()) return false;
+
+			string::size_type left = str.find('[');
+			// 没有找到[号
+			if(left == string::npos)
+				return false;
+
+			string::size_type right = str.rfind(']');
+
+			if(right == string::npos)return false;
+			if(right < left)return false;
+
+			left++;
+			lpIniGrop->name = str.substr(left, right - left);
+
+			string::size_type tag = str.find(note);
+			if(tag != string::npos && tag > right)
+			{
+				++tag;
+				lpIniGrop->Note = str.substr(tag, str.length() - tag);
+			}
+
+			return true;
+		}
+
+		//解析元素
+		static bool ParseItem(const string& str ,LPINIITEM lpIniItem,char note = ';' )
+		{
+			if(str.empty()) return false;
+
+			string tempKey = "";
+			string tempValue = "";
+			string tempNote = "";
+			string::size_type pos = str.find('=');//查找 = 位置
+			string::size_type right = str.length();//获取数据长度
+			string::size_type cnote = str.find(note);
+			//未找到 “=”
+			if((pos == string::npos)||(pos == 0))return false;
+			if((cnote!=string::npos)&&(cnote<=pos))return false;
+
+			tempKey= str.substr(0,pos);
+			++pos;
+
+			if(cnote != string::npos)
+			{
+				tempValue = str.substr(pos,cnote-pos);
+				++cnote;
+				tempNote = str.substr(cnote,right - cnote);
+
+			}
+			else
+				tempValue = str.substr(pos,right - pos);
+
+			//cout<<tempKey<<"--"<<tempValue<<"++"<<tempNote<<endl;
+			int i_not_pos_start = 0;int i_not_pos_end = 0;
+
+			i_not_pos_start = tempKey.find_first_not_of(" ");
+			i_not_pos_end = tempKey.find_last_not_of(" ");
+			if((i_not_pos_start >= i_not_pos_end))lpIniItem->Key = "";
+			else lpIniItem->Key = str.substr(i_not_pos_start,i_not_pos_end - i_not_pos_start +1);
+
+			i_not_pos_start = tempValue.find_first_not_of(" ");
+			i_not_pos_end = tempValue.find_last_not_of(" ");
+			if((i_not_pos_start >= i_not_pos_end))
+				lpIniItem->Value = "";
+			else lpIniItem->Value = tempValue.substr(i_not_pos_start,i_not_pos_end - i_not_pos_start +1);
+
+			i_not_pos_start = tempNote.find_first_not_of(" ");
+			i_not_pos_end = tempNote.find_last_not_of(" ");
+			if((i_not_pos_start >= i_not_pos_end))
+				lpIniItem->Note = "";
+			else lpIniItem->Note = tempNote.substr(i_not_pos_start,i_not_pos_end - i_not_pos_start +1);
+			return true;
+		}
+};
+#endif

+ 22 - 0
DevAdapter/nantian/pinpad.1.1/CMakeLists.txt

@@ -0,0 +1,22 @@
+# 声明模块名称的前缀和名称
+rvc_dev_define_module("PinPad")
+
+# rvc_dev_config_library 内需要使用这三个参数,用于拼接输出的适配器文件名称
+set(${MODULE_PREFIX}_VENDOR "nantian")
+set(${MODULE_PREFIX}_VERSION "1")
+set(${MODULE_PREFIX}_BATCH "1")
+
+# 包含要编译的实现文件,rvc_dev_config_library 内使用
+set(${MODULE_PREFIX}_SRCS SHARED
+        pinpad.nantian.1.1.cpp   
+        )
+
+# 适配器工程需要通过此宏替代 add_library
+rvc_dev_config_library(${MODULE_NAME} ${MODULE_PREFIX})
+
+# ${MODULE_FULL_NAME} 是 TAGET 名称,在 rvc_dev_config_library 中定义
+target_include_directories(${MODULE_FULL_NAME} PRIVATE "${VENDOR_CURRENT_DEPS_DIR}/cmbsz.sample")
+target_link_libraries(${MODULE_FULL_NAME} sample ${VENDOR_LOG_LIB_NAME})
+
+#  =-=-=-=-=-=-=-=-=-= {适配器工程}/CMakeLists.txt 文件最后必须声明如下内容=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=
+rvc_dev_target_install(${MODULE_FULL_NAME})

+ 1339 - 0
DevAdapter/nantian/pinpad.1.1/pinpad.nantian.1.1.cpp

@@ -0,0 +1,1339 @@
+
+#include "pinpad.nantian.1.1.h"
+
+#include <cstring>
+#include <cstdio>
+
+//日志类
+CILIXTrace* m_trace;
+
+PinPadNantian::PinPadNantian()
+{
+    m_trace = new CILIXTrace(NULL, "Nantian", "Pinpad");
+    m_trace->WriteTrace("PinPadNantian", "pinpad.Nantian.1.1.so - 1.0.0.1");
+
+    char SOPath[100] = "";
+    CILIX_AUX_X::CILIX_GetModuleCurPath(SOPath);
+    void *handle;
+    strcat(SOPath, "libXZ_F35_API_LINUX.nantian.so");
+    m_trace->WriteTrace("PinPadNantian", "SOPath = %s", SOPath);
+    handle=dlopen(SOPath,RTLD_LAZY);
+    if(handle == NULL)
+    {
+        m_trace->WriteTrace("PinPadNantian", "Load libXZ_F35_API_LINUX.nantian.so Fail");
+        m_trace->WriteTrace("PinPadNantian", "Exit-");
+        return ;
+    }
+    m_trace->WriteTrace("PinPadNantian", "Load libXZ_F35_API_LINUX.nantian.so Success");
+
+    SUNSON_OpenCom=(int(*)(const char *, long))dlsym(handle,"SUNSON_OpenCom");
+    SUNSON_GetVersionNo=(int(*)(unsigned char *))dlsym(handle,"SUNSON_GetVersionNo");
+    SUNSON_CloseCom=(int(*)(void))dlsym(handle,"SUNSON_CloseCom");
+    SUNSON_ScanGetKey=(int(*)(unsigned char *))dlsym(handle,"SUNSON_ScanGetKey");
+    SUNSON_CloseEppPlainTextMode=(int(*)(unsigned char *))dlsym(handle,
+                                                                "SUNSON_CloseEppPlainTextMode");
+    SUNSON_LoadSM4Key=(int(*)(int, int, int, unsigned char, unsigned char *, unsigned char *))dlsym(handle,
+                                                     "SUNSON_LoadSM4Key");
+    SUNSON_LoadUserKey=(int(*)(int, int, long, unsigned char, unsigned char *, unsigned char *))dlsym(handle,
+                                                                                                      "SUNSON_LoadUserKey");
+    SUNSON_SetKeyMark=(int(*)(long, long, long, long, unsigned char*))dlsym(handle,
+                                                                            "SUNSON_SetKeyMark");
+    SUNSON_GetPin=(int(*)(unsigned char, unsigned char, unsigned char, unsigned char *))dlsym(handle,
+                                                                                              "SUNSON_GetPin");
+    SUNSON_UseEppPlainTextMode=(int(*)(unsigned char, unsigned char, unsigned char *))dlsym(handle,
+                                                                                            "SUNSON_UseEppPlainTextMode");
+    SUNSON_SwitchArithmetic=(int(*)(unsigned char, unsigned char *))dlsym(handle, "SUNSON_SwitchArithmetic");
+    SUNSON_GetPinBlock=(int(*)(int, int, unsigned char, unsigned char, unsigned char*, unsigned char*))dlsym(handle,
+                                                                                                             "SUNSON_GetPinBlock");
+    SUNSON_DataCompute=(int(*)(int, unsigned char, int, unsigned char, int, unsigned char *, unsigned char *))dlsym(handle,
+                                                                                                                    "SUNSON_DataCompute");
+    SUNSON_MakeMac=(int(*)(int, int, int, unsigned char *, unsigned char *))dlsym(handle, "SUNSON_MakeMac");
+    SUNSON_ScanKeyPress=(int(*)(unsigned char *))dlsym(handle, "SUNSON_ScanKeyPress");
+}
+
+PinPadNantian::~PinPadNantian()
+{
+
+}
+
+DEVICEBASE_API ErrorCodeEnum CreateDevComponent(DeviceBaseClass*& pOutDevAptObj)
+{
+    pOutDevAptObj = new PinPadNantian();
+    if(pOutDevAptObj == NULL)
+    {
+        return Error_Resource;
+    }
+
+    /*cmb::log_init_config config;
+    config.dev_name = "pinpad";
+    config.log_dir = ("/etc/nantian");
+
+    std::string str;
+    cmb::log4vendor::init(config, str);
+    char msg[100];
+    LOG4VTM(TRACE, "<CreateDevComponent> - 执行init()返回信息:"<<str.c_str());*/
+
+    return Error_Succeed;
+}
+
+DEVICEBASE_API ErrorCodeEnum  ReleaseDevComponent(DeviceBaseClass*& pInDevAptObj)
+{
+    if(pInDevAptObj == NULL)
+    {
+        return Error_Param;
+    }
+    if(PinPadNantian* pTmp = dynamic_cast<PinPadNantian*>(pInDevAptObj))
+    {
+        delete pTmp;
+        pTmp = NULL;
+        return Error_Succeed;
+    }
+    return Error_Param;
+
+}
+
+ErrorCodeEnum PinPadNantian::GetDevCategory(DevCategoryInfo &devCategory)
+{
+    m_trace->WriteTrace("GetDevCategory","Enter-");
+
+    //赋值
+    strcpy(devCategory.szType,"PinPad");
+    strcpy(devCategory.szVendor,"nantian");
+    devCategory.version.wMajor = 1;
+    devCategory.version.wMinor = 0;
+    devCategory.version.wRevision = 0;
+    devCategory.version.wBuild = 1;
+
+    //设备未连接
+    if(m_Open == false)
+    {
+            strcpy(devCategory.szModel,"");
+            devCategory.eState = DEVICE_STATUS_NOT_READY;
+            m_trace->WriteTrace("GetDevCategory", "设备未连接");
+            m_trace->WriteTrace("GetDevCategory", "Exit-");
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"设备未连接");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+            return Error_Succeed;
+    }
+
+    strcpy(devCategory.szModel,"SE8098BV1.0");
+
+    char ver[100] = "";
+    int sret = SUNSON_GetVersionNo((unsigned char *)ver);
+    m_trace->WriteTrace("GetDevCategory","执行SUNSON_GetVersionNo返回%d", sret);
+    if (sret == 0)
+    {
+            m_trace->WriteTrace("GetDevCategory", "查设备状态失败");
+            m_trace->WriteTrace("GetDevCategory", "Exit-");
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"查设备状态失败");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+            devCategory.eState = DEVICE_STATUS_FAULT;
+    }
+
+    m_trace->WriteTrace("GetDevCategory", "Exit-");
+    devCategory.eState = DEVICE_STATUS_NORMAL;
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::Reset()
+{
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::DevClose()
+{
+    SUNSON_CloseCom();
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::GetLastErr(DevErrorInfo &devErrInfo)
+{
+    memset(devErrInfo.szErrMsg,0,sizeof(devErrInfo.szErrMsg));
+    devErrInfo.dwErrMsgLen = m_Error.dwErrMsgLen;
+    memcpy(devErrInfo.szErrMsg,m_Error.szErrMsg,m_Error.dwErrMsgLen);
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::DevOpen(DWORD dwPort, DWORD dwBaudRate)
+{
+    /*LOG4VTM(TRACE, "<DevOpen> - "<<"Enter-");
+    LOG4VTM(TRACE, "<DevOpen> - "<<"dwPort = "<<dwPort<<", dwBaudRate = "<<dwBaudRate);*/
+
+    m_trace->WriteTrace("DevOpen","Enter-");
+    m_trace->WriteTrace("DevOpen","dwPort = %d", dwPort);
+
+    char sztty[100];
+    sprintf(sztty, "/dev/ttyXRUSB%d", dwPort-1);
+    m_trace->WriteTrace("DevOpen","sztty = %s", sztty);
+
+    int sret = SUNSON_OpenCom(sztty, 9600);
+    m_trace->WriteTrace("DevOpen","执行SUNSON_OpenCom返回%d", sret);
+    if (sret != 1)
+    {
+        m_trace->WriteTrace("DevOpen", "设备打开失败");
+        m_trace->WriteTrace("DevOpen", "Exit-");
+
+        m_Open = FALSE;
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备打开失败");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        return Error_DevConnFailed;
+    }
+
+    m_trace->WriteTrace("DevOpen", "设备打开成功");
+    m_trace->WriteTrace("DevOpen", "Exit-");
+    m_Open = TRUE;
+    memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+    strcpy(m_Error.szErrMsg,"设备打开成功");
+    m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::KeyRead(BYTE &ch)
+{
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("KeyRead","设备未打开");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开,不能做键值读取操作");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        return Error_NotInit;
+    }
+
+    //按键值
+    unsigned char fKey = 0;
+    int iret = SUNSON_ScanKeyPress(&fKey);
+    //********无按键
+    if (iret == 0)
+    {
+        return Error_DevCommFailed;
+    }
+
+    unsigned char fResult[100] = "";
+    //********有按键
+    if (iret == 1)
+    {
+        if (g_flag == 1)//密文模式
+        {
+            //密码键
+            if (fKey == 0x2A)
+            {
+                m_trace->WriteTrace("KeyRead", "keypress *");
+                //记录输入位数
+                m_PinNum++;
+
+                if (m_PinNum>=6 && g_Auto == 1)
+                {
+                    //输入终止
+                    ch = 0x3f;
+                    SUNSON_CloseEppPlainTextMode(fResult);
+                    m_trace->WriteTrace("KeyRead", "键盘关闭");
+                }
+                else
+                {
+                    ch = 0x3f;
+                }
+            }
+
+            //Enter
+            if (fKey == 0x0D)
+            {
+                if(g_Auto == 0)
+                {
+                    m_trace->WriteTrace("KeyRead", "keypress Enter");
+                    ch = 0x0D;
+                    SUNSON_CloseEppPlainTextMode(fResult);
+                    m_trace->WriteTrace("KeyRead", "键盘关闭");
+                }
+                else
+                {
+                    return Error_DevCommFailed;
+                }
+            }
+
+            //Up
+            if (fKey == 0x54)
+            {
+                m_trace->WriteTrace("KeyRead", "keypress Up");
+                return Error_DevCommFailed;
+            }
+
+            //Down
+            if (fKey == 0x23)
+            {
+                m_trace->WriteTrace("KeyRead", "keypress Down");
+                return Error_DevCommFailed;
+            }
+
+            //Cancel
+            if (fKey == 0x1B)
+            {
+                ch = 0x1B;
+                m_trace->WriteTrace("KeyRead", "keypress CANCEL");
+                //清空输入
+                m_PinNum = 0;
+            }
+
+            //Backspace
+            if (fKey == 0x08)
+            {
+                m_trace->WriteTrace("KeyRead", "keypress BACKSPACE");
+                ch = 0x08;
+                //后退一格
+                if (m_PinNum > 0)
+                        m_PinNum --;
+                //清空输入
+                m_PinNum = 0;
+            }
+        }
+        if (g_flag == 0)//明文模式
+        {
+            m_trace->WriteTrace("KeyRead", "fKey = 0x%02X",fKey);
+            switch(fKey)
+            {
+                case 0x30://0
+                        ch = 0x30;
+                        m_trace->WriteTrace("KeyRead", "keypress 0");
+                        break;
+                case 0x31://1
+                        ch = 0x31;
+                        m_trace->WriteTrace("KeyRead", "keypress 1");
+                        break;
+                case 0x32://2
+                        ch = 0x32;
+                        m_trace->WriteTrace("KeyRead", "keypress 2");
+                        break;
+                case 0x33://3
+                        ch = 0x33;
+                        m_trace->WriteTrace("KeyRead", "keypress 3");
+                        break;
+                case 0x34://4
+                        ch = 0x34;
+                        m_trace->WriteTrace("KeyRead", "keypress 4");
+                        break;
+                case 0x35://5
+                        ch = 0x35;
+                        m_trace->WriteTrace("KeyRead", "keypress 5");
+                        break;
+                case 0x36://6
+                        ch = 0x36;
+                        m_trace->WriteTrace("KeyRead", "keypress 6");
+                        break;
+                case 0x37://7
+                        ch = 0x37;
+                        m_trace->WriteTrace("KeyRead", "keypress 7");
+                        break;
+                case 0x38://8
+                        ch = 0x38;
+                        m_trace->WriteTrace("KeyRead", "keypress 8");
+                        break;
+                case 0x39://9
+                        ch = 0x39;
+                        m_trace->WriteTrace("KeyRead", "keypress 9");
+                        break;
+                case 0x08://BackSpace
+                        ch = 0x08;
+                        m_trace->WriteTrace("KeyRead", "keypress BackSpace");
+                        break;
+                case 0x2e://.
+                        ch = 0x2e;
+                        m_trace->WriteTrace("KeyRead", "keypress .");
+                        break;
+                case 0x0d://ENTER
+                        ch = 0x0d;
+                        m_trace->WriteTrace("KeyRead", "keypress ENTER");
+                        break;
+                case 0x1b:////ESC
+                        ch = 0x1b;
+                        m_trace->WriteTrace("KeyRead", "keypress ESC");
+                        break;
+                case 0x54:////00
+                        ch = 0x4f;
+                        m_trace->WriteTrace("KeyRead", "keypress 00");
+                        break;
+                case 0x23:////ESC
+                        ch = 0x23;
+                        m_trace->WriteTrace("KeyRead", "keypress DOWN");
+                        break;
+                default:
+                        ch = 0x00;
+                        break;
+            }
+        }
+    }
+
+    m_trace->WriteTrace("KeyRead", "获取键值成功,获取的键值为0x%02X",ch);
+    memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+    strcpy(m_Error.szErrMsg,"获取键值成功");
+    m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+    return Error_Succeed;
+}
+
+int m_Encryptmethod;
+int m_MacAlgorithm;
+int m_PinAlgorithm;
+int m_ECB_CBC_Mode;
+
+ErrorCodeEnum PinPadNantian::SetParam(SetParamTypeEnum eType, SetParamValueEnum eValue)
+{
+    m_trace->WriteTrace("SetParam","Enter-");
+    m_trace->WriteTrace("SetParam","eType = %d, eValue = %d",eType, eValue);
+
+    switch (eType)
+    {
+        case EPP_PT_SET_ENCRYPT_METHOD:
+            if (eValue == EPP_ALGO_METHOD_DES)
+            {
+                m_Encryptmethod = 0;
+            }
+            else if (eValue == EPP_ALGO_METHOD_3DES)
+            {
+                m_Encryptmethod = 1;
+            }
+            else if (eValue == EPP_ALGO_METHOD_DES_TMK)
+            {
+                m_Encryptmethod = 2;
+            }
+            else if (eValue == EPP_ALGO_METHOD_3DES_TMK)
+            {
+                m_Encryptmethod = 3;
+            }
+            else if (eValue == EPP_ALGO_METHOD_SM4)
+            {
+                m_Encryptmethod = 4;
+            }
+            else
+            {
+                m_trace->WriteTrace("SetParam","EPP_PT_SET_ENCRYPT_METHOD中的eValue值不符合");
+                memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+                strcpy(m_Error.szErrMsg,"参数错误");
+                m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+                return Error_Param;
+            }
+            break;
+        case EPP_PT_SET_MAC_ALGORITH:
+            if (eValue == EPP_MAC_ALGO_ASNIX99)
+            {
+                if (m_Encryptmethod == 0) //DES
+                {
+                         m_MacAlgorithm = 1;
+                }
+                else if (m_Encryptmethod == 1) //3DES
+                {
+                        m_MacAlgorithm = 2;
+                }
+                else if (m_Encryptmethod == 4) //SM4
+                {
+                        m_MacAlgorithm = 3;
+                }
+            }
+            else if (eValue == EPP_MAC_ALGO_PBOC)
+            {
+                m_trace->WriteTrace("SetParam","不支持除了EPP_MAC_ALGO_ASNIX99以外的其它MAC算法");
+                memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+                strcpy(m_Error.szErrMsg,"不支持的算法");
+                m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+                return Error_NoPrivilege;
+            }
+            else if (eValue == EPP_MAC_ALGO_UNIONPAY)
+            {
+                m_trace->WriteTrace("SetParam","不支持除了EPP_MAC_ALGO_ASNIX99以外的其它MAC算法");
+                memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+                strcpy(m_Error.szErrMsg,"不支持的算法");
+                m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+                return Error_NoPrivilege;
+            }
+            else
+            {
+                m_trace->WriteTrace("SetParam","EPP_PT_SET_MAC_ALGORITH的eValue值不符合");
+                memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+                strcpy(m_Error.szErrMsg,"参数错误");
+                m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+                return Error_Param;
+            }
+            break;
+        case EPP_PT_SET_PIN_ALGORITH:
+            if (eValue == EPP_PIN_ALGO_ISO9564_1_ANSI)
+            {
+                //确定为ANSI算法
+                m_PinAlgorithm = 1; //ANSI算法
+            }
+            else if (eValue == EPP_PIN_ALGO_IBM3624)
+            {
+                //确定为IBM3624算法
+                m_PinAlgorithm = 2; //IBM3624算法
+            }
+            else if (eValue == EPP_PIN_ALGO_SM4)
+            {
+                m_PinAlgorithm = 3;
+            }
+            else
+            {
+                m_trace->WriteTrace("SetParam","EPP_PT_SET_PIN_ALGORITH的eValue值不符合");
+                memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+                strcpy(m_Error.szErrMsg,"参数错误");
+                m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+                return Error_Param;
+            }
+            break;
+        case EPP_PT_SET_ECB_CBC_MODE:
+            if (eValue == EPP_ALGO_MODE_ECB || eValue == EPP_ALGO_MODE_DEC_ECB || eValue == EPP_ALGO_MODE_3DEC_ECB)
+            {
+                m_ECB_CBC_Mode = 1;
+            }
+            else if (eValue == EPP_ALGO_MODE_CBC || eValue == EPP_ALGO_MODE_DEC_CBC || eValue == EPP_ALGO_MODE_3DEC_CBC)
+            {
+                m_ECB_CBC_Mode = 2;
+            }
+            else
+            {
+                m_trace->WriteTrace("SetParam","EPP_PT_SET_ECB_CBC_MODE的eValue值不符合");
+                memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+                strcpy(m_Error.szErrMsg,"参数错误");
+                m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+                return Error_Param;
+            }
+            break;
+        default:
+            m_trace->WriteTrace("SetParam","参数错误");
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"参数错误");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+            return Error_Param;
+            break;
+    }
+
+    m_trace->WriteTrace("SetParam", "Exit-");
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::SetAccNo(AccountInfo accInfo)
+{
+    m_trace->WriteTrace("SetAccNo","Enter-");
+
+    m_trace->WriteTrace("SetAccNo","accInfo.dwAccLen = %d", accInfo.dwAccLen);
+
+    m_trace->WriteTrace(CILIXTRACE_L_DEBUG, "SetAccNo", "accInfo.account = %s", accInfo.account);
+
+    if (accInfo.dwAccLen < 0 || accInfo.dwAccLen > 12)
+    {
+        m_trace->WriteTrace("SetAccNo","输入的客户账号长度错误,账号长度为 accInfo.dwAccLen =  %d",
+                            accInfo.dwAccLen);
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"参数错误");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("SetAccNo", "Exit-");
+        return Error_Param;
+    }
+    if (accInfo.account == NULL)
+    {
+        m_trace->WriteTrace("SetAccNo","输入的客户账号为空");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"参数为空");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("SetAccNo", "Exit-");
+        return Error_Null;
+    }
+
+    g_CardNo.dwAccLen = accInfo.dwAccLen;
+    memset(g_CardNo.account,0,sizeof(g_CardNo.account));
+    memcpy(g_CardNo.account,accInfo.account,accInfo.dwAccLen);
+    strcpy(m_Error.szErrMsg,"设置账户信息成功");
+    m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+    m_trace->WriteTrace("SetAccNo", "Exit-");
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::LoadMasterKey(MasterKeyParam masterKey)
+{
+    m_trace->WriteTrace("LoadMasterKey","Enter-");
+
+    m_trace->WriteTrace("LoadMasterKey", "masterKey.dwMasterSN = %d", masterKey.dwSN);
+    m_trace->WriteTrace(CILIXTRACE_L_DEBUG, "LoadMasterKey", "masterKey.key = %s", masterKey.key);
+
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("LoadMasterKey","设备未打开,不能做加载主密钥操作");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("LoadMasterKey", "Exit-");
+        return Error_NotInit;
+    }
+    if ((masterKey.smFlag != 0 && masterKey.smFlag != 1) || (masterKey.key == NULL) ||
+        (masterKey.dwSN < 0 ))
+    {
+        m_trace->WriteTrace("LoadMasterKey","输入参数错误或为空");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"输入参数错误或为空");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("LoadMasterKey", "Exit-");
+        return Error_Param;
+    }
+
+    //压缩数据
+    unsigned char fswData[1025] = "";
+    CILIX_AUX_X::CILIX_uti_pack((unsigned char*)masterKey.key, fswData, 32);
+
+    //导入
+    if (masterKey.smFlag == 1)//国密
+    {
+        if (masterKey.dwSN < 0 || masterKey.dwSN > 12 || masterKey.key == NULL)
+        {
+            m_trace->WriteTrace("LoadMasterKey","国密:输入秘钥号超出键盘规定的最大值");
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"输入参数错误");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+            m_trace->WriteTrace("LoadMasterKey", "Exit-");
+            return Error_Param;
+        }
+
+        unsigned char fResult[1025] = "";
+        int sret = SUNSON_LoadSM4Key(masterKey.dwSN, 65535, 0x27, 16, (unsigned char*)fswData,
+                                     fResult);
+        m_trace->WriteTrace("LoadMasterKey","国密:加载主密钥操作返回值sret = %d,fResult[0] = 0x%02x",
+                            sret,fResult[0]);
+        if (sret != 1)
+        {
+                memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+                strcpy(m_Error.szErrMsg,"导入SM4主密钥失败");
+                m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+                m_trace->WriteTrace("LoadMasterKey", "Exit-");
+                return Error_Hardware;
+        }
+        m_trace->WriteTrace("LoadMasterKey","国密:加载主密钥操作成功");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"操作成功");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        return Error_Succeed;
+    }
+    else
+    {
+        masterKey.dwSN += 10;
+        if (masterKey.dwSN < 0 || masterKey.dwSN > 63 || masterKey.key == NULL)
+        {
+            m_trace->WriteTrace("LoadMasterKey","非国密:输入秘钥号超出键盘规定的最大值");
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"输入参数错误");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+            m_trace->WriteTrace("LoadMasterKey", "Exit-");
+            return Error_Param;
+        }
+
+        unsigned char fResult[1025] = "";
+        int sret = SUNSON_LoadUserKey(masterKey.dwSN, 65535, 0x27, 16, (unsigned char*)fswData, fResult);
+        m_trace->WriteTrace("LoadMasterKey","非国密:invoke SUNSON_LoadUserKey,sret = %d,fResult[0] = 0x%02x",sret,fResult[0]);
+        if (sret != 1)
+        {
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"导入3DES主密钥失败");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+            m_trace->WriteTrace("LoadMasterKey", "Exit-");
+            return Error_Hardware;
+        }
+
+        m_trace->WriteTrace("LoadMasterKey","非国密:加载3DES主密钥操作成功");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"操作成功");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("LoadMasterKey", "Exit-");
+        return Error_Succeed;
+    }
+}
+
+ErrorCodeEnum PinPadNantian::LoadWorkingKey(WorkKeyParam wkKey)
+{
+    m_trace->WriteTrace("LoadWorkingKey","Enter-");
+
+    m_trace->WriteTrace("LoadWorkingKey","wkKey.dwMasterSN = %d, wkKey.dwWorkingSN = %d",
+                        wkKey.dwMasterSN, wkKey.dwWorkingSN);
+    m_trace->WriteTrace(CILIXTRACE_L_DEBUG, "LoadWorkingKey","wkKey.key = %s", wkKey.key);
+
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("LoadWorkingKey","设备未打开,不能做加载主密钥操作");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("LoadWorkingKey", "Exit-");
+        return Error_NotInit;
+    }
+    if ((wkKey.smFlag != 0 && wkKey.smFlag != 1) || (wkKey.dwMasterSN < 0 || wkKey.dwWorkingSN < 0) || (wkKey.key == NULL))
+    {
+        m_trace->WriteTrace("LoadWorkingKey","输入参数错误或为空");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"输入参数错误或为空");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("LoadWorkingKey", "Exit-");
+        return Error_Param;
+    }
+
+    unsigned char fswData[1025] = "";
+    CILIX_AUX_X::CILIX_uti_pack((unsigned char*)wkKey.key, fswData, 32);
+
+    if (wkKey.smFlag == 1)//国密
+    {
+        wkKey.dwWorkingSN += 2;
+        if (wkKey.dwWorkingSN <0 || wkKey.dwWorkingSN > 12 || wkKey.dwMasterSN < 0 || wkKey.dwMasterSN > 12 || wkKey.key == NULL)
+        {
+            m_trace->WriteTrace("LoadWorkingKey","国密:输入秘钥号处理后,超出键盘规定的最大值输入秘钥号");
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"输入参数错误");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+            return Error_Param;
+        }
+        //导入
+        unsigned char fResult[1025] = "";
+        int sret = SUNSON_LoadSM4Key(wkKey.dwWorkingSN, wkKey.dwMasterSN, 0x07, 16, fswData, fResult);
+        m_trace->WriteTrace("LoadWorkingKey","国密:加载工作密钥操作返回值sret = %d,fResult[0] = 0x%02x",sret,fResult[0]);
+        if (sret != 1)
+        {
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"导入SM4工作密钥失败");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+            m_trace->WriteTrace("LoadWorkingKey", "Exit-");
+            return Error_Hardware;
+        }
+        m_trace->WriteTrace("LoadWorkingKey","国密:加载SM4工作密钥操作成功");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"操作成功");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        return Error_Succeed;
+    }
+    else
+    {
+        wkKey.dwWorkingSN += 11;
+        wkKey.dwMasterSN += 10;
+        if (wkKey.dwWorkingSN <0 || wkKey.dwWorkingSN > 64 || wkKey.dwMasterSN < 0 || wkKey.dwMasterSN > 32 || wkKey.key == NULL)
+        {
+            m_trace->WriteTrace("LoadWorkingKey","非国密:超出键盘规定的最大值输入秘钥号");
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"输入参数错误");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+            m_trace->WriteTrace("LoadWorkingKey", "Exit-");
+            return Error_Param;
+        }
+
+        unsigned char fResult[1025] = "";
+        int sret = SUNSON_LoadUserKey(wkKey.dwWorkingSN, wkKey.dwMasterSN, 0x07, 16, (unsigned char*)fswData, fResult);
+        m_trace->WriteTrace("LoadWorkingKey","非国密:invoke SUNSON_LoadUserKey,sret = %d,fResult[0] = 0x%02x",sret,fResult[0]);
+        if (sret != 1)
+        {
+                memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+                strcpy(m_Error.szErrMsg,"导入3DES工作密钥失败");
+                m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+                m_trace->WriteTrace("LoadWorkingKey", "Exit-");
+                return Error_Hardware;
+        }
+
+        m_trace->WriteTrace("LoadWorkingKey","非国密:加载3DES工作密钥操作成功");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"操作成功");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("LoadWorkingKey", "Exit-");
+        return Error_Succeed;
+    }
+}
+
+ErrorCodeEnum PinPadNantian::ActiveWorkingKey(DWORD dwMkSN, DWORD dwWkSN)
+{
+    m_trace->WriteTrace("ActiveWorkingKey","Enter-");
+
+    m_trace->WriteTrace("ActiveWorkingKey","dwMkSN = %d,dwWkSN = %d",dwMkSN,dwWkSN);
+
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("ActiveWorkingKey", "设备未打开,不能做激活工作秘钥操作");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("ActiveWorkingKey", "Exit-");
+        return Error_NotInit;
+    }
+
+    g_dwMkSN = dwMkSN;
+    g_dwWkSN = dwWkSN;
+
+    memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+    strcpy(m_Error.szErrMsg,"操作成功");
+    m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+    m_trace->WriteTrace("ActiveWorkingKey", "Exit-");
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::StartPinInput(BYTE byLen)
+{
+    m_trace->WriteTrace("StartPinInput","Enter-");
+
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("StartPinInput","设备未打开,不能做Pin输入操作");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("StartPinInput", "Exit-");
+        return Error_NotInit;
+    }
+
+    char fResult[1025] = "";
+    SUNSON_SetKeyMark(0x1FFF, 0, 0, 0, (unsigned char*)fResult);
+
+    //重置输入位数
+    m_PinNum = 0;
+    g_flag = 1;//标记是密文输入
+    g_Auto = 1;//标记自动结束
+
+    memset(fResult,0,sizeof(fResult));
+    //激活密码输入
+    int iret = SUNSON_GetPin(1, 6, 0x01, (unsigned char*)fResult);
+    m_trace->WriteTrace("StartPinInput", "invoke SUNSON_GetPin return %d, fResult[0] = 0x%02x", iret, fResult[0]);
+    if (iret != 1)
+    {
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"开启密文输入失败");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("StartPinInput", "Exit-");
+        return Error_Hardware;
+    }
+
+    memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+    strcpy(m_Error.szErrMsg,"操作成功");
+    m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+    m_trace->WriteTrace("StartPinInput", "Exit-");
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::StartPinInputConfirm(BYTE byLen)
+{
+    m_trace->WriteTrace("StartPinInputConfirm","Enter-");
+
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("StartPinInputConfirm","设备未打开,不能做Pin输入操作");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("StartPinInputConfirm", "Exit-");
+        return Error_NotInit;
+    }
+
+    char fResult[1025] = "";
+    SUNSON_SetKeyMark(0x1FFF, 0, 0, 0, (unsigned char*)fResult);
+
+    //重置输入位数
+    m_PinNum = 0;
+    g_flag = 1;//标记是密文输入
+    g_Auto = 0;//标记自动结束
+
+    memset(fResult,0,sizeof(fResult));
+    //激活密码输入
+    int iret = SUNSON_GetPin(1, 6, 0x00, (unsigned char*)fResult);
+    m_trace->WriteTrace("StartPinInputConfirm", "invoke SUNSON_GetPin return %d, fResult[0] = 0x%02x", iret, fResult[0]);
+    if (iret != 1)
+    {
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"开启密文输入失败");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("StartPinInputConfirm", "Exit-");
+        return Error_Hardware;
+    }
+
+    memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+    strcpy(m_Error.szErrMsg,"操作成功");
+    m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+    m_trace->WriteTrace("StartPinInputConfirm", "Exit-");
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::StartPlainInput()
+{
+    m_trace->WriteTrace("StartPlainInput","Enter-");
+
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("StartPlainInput","设备未打开,不能做明文输入操作");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("StartPlainInput", "Exit-");
+        return Error_NotInit;
+    }
+
+    char fResult[1025] = "";
+    SUNSON_SetKeyMark(0x1AFFF, 0, 0, 0, (unsigned char*)fResult);
+
+    g_flag = 0;//标记是明文输入
+
+    //激活密码输入
+    memset(fResult, 0, sizeof(fResult));
+    int iret = SUNSON_UseEppPlainTextMode(0,0,(unsigned char*)fResult);
+    m_trace->WriteTrace("StartPlainInput", "invoke SUNSON_UseEppPlainTextMode return %d, fResult[0] = 0x%02x", iret,fResult[0]);
+    if (iret != 1)
+    {
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"开启明文输入失败");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+        m_trace->WriteTrace("StartPlainInput", "Exit-");
+        return Error_Hardware;
+    }
+
+    memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+    strcpy(m_Error.szErrMsg,"操作成功");
+    m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+    m_trace->WriteTrace("StartPlainInput", "Exit-");
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::StopInput()
+{
+    m_trace->WriteTrace("StopInput","Enter-");
+
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("StopInput","设备未打开,直接返回");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("StopInput", "Exit-");
+        return Error_NotInit;
+    }
+
+    unsigned char fResult[1025] = "";
+    int iret = SUNSON_CloseEppPlainTextMode(fResult);
+    m_trace->WriteTrace("StopInput","执行SUNSON_CloseEppPlainTextMode返回%d,fResult[0] = 0x%02x",iret,fResult[0]);
+    if (iret == 0)
+    {
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"键盘关闭失败");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("StopInput", "Exit-");
+        return Error_DevCommFailed;
+    }
+
+    memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+    strcpy(m_Error.szErrMsg,"键盘关闭成功");
+    m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+    m_trace->WriteTrace("StopInput", "Exit-");
+    return Error_Succeed;
+}
+
+ErrorCodeEnum PinPadNantian::GetPinBlock(PinBlock &block)
+{
+    m_trace->WriteTrace("GetPinBlock","Enter-");
+
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("GetPinBlock","设备未打开,不能做GetPinBlock操作");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("GetPinBlock", "Exit-");
+        return Error_NotInit;
+    }
+
+    m_trace->WriteTrace("GetPinBlock","g_dwWkSN = %d",g_dwWkSN);
+
+    int WkSN = 0;
+
+    if (m_PinAlgorithm == 3)
+    {
+        char ReturnInfo[100] = "";
+        int sret = SUNSON_SwitchArithmetic(2, (unsigned char *)ReturnInfo);
+        m_trace->WriteTrace("GetPinBlock","国密:invoke SUNSON_SwitchArithmetic,sret = %d, ReturnInfo[0] = 0x%02x",sret, ReturnInfo[0]);
+        if (sret != 1)
+        {
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"切换国密算法失败");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+            m_trace->WriteTrace("GetPinBlock", "Exit-");
+            return Error_DevMedia;
+        }
+
+        if(g_dwWkSN == 99)
+        {
+                WkSN = g_dwMkSN;
+        }
+        else
+        {
+                WkSN = g_dwWkSN + 2;
+        }
+    }
+    else
+    {
+        char ReturnInfo[100] = "";
+        int sret = SUNSON_SwitchArithmetic(0, (unsigned char *)ReturnInfo);
+        m_trace->WriteTrace("GetPinBlock","非国密:invoke SUNSON_SwitchArithmetic,sret = %d, ReturnInfo[0] = 0x%02x",sret, ReturnInfo[0]);
+        if (sret != 1)
+        {
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"切换非国密算法失败");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+            m_trace->WriteTrace("GetPinBlock", "Exit-");
+            return Error_DevMedia;
+        }
+
+        if(g_dwWkSN == 99)
+        {
+            WkSN = g_dwMkSN;
+        }
+        else
+        {
+            WkSN = g_dwWkSN + 11;
+        }
+    }
+
+    unsigned char fResult[1025] = "";
+    //计算PINBLOCK
+    int sret = SUNSON_GetPinBlock(WkSN,0x02,0x0F,g_CardNo.dwAccLen,(unsigned char*)g_CardNo.account,fResult);
+    m_trace->WriteTrace("GetPinBlock", "invoke  SUNSON_GetPinBlock return %d,f_result[0] = 0x%02X", sret,fResult[0]);
+    memset(block.data,0,sizeof(block.data));
+    if(sret > 0)
+    {
+        //扩展并拷贝计算结果
+        CILIX_AUX_X::CILIX_uti_unpack(fResult, (unsigned char*)block.data, sret);
+        block.dwSize = sret*2;
+        m_trace->WriteTrace("GetPinBlock","GetPinBlock操作成功");
+        m_trace->WriteTrace(CILIXTRACE_L_DEBUG, "GetPinBlock", "block.data=%s",block.data);
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"操作成功");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("GetPinBlock", "Exit-");
+        return Error_Succeed;
+    }
+    else
+    {
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"获取pinblock失败");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("EncryptData", "Exit-");
+        return Error_Hardware;
+    }
+}
+
+ErrorCodeEnum PinPadNantian::EncryptData(EnDecryptInfo srcInfo, EnDecryptInfo &destInfo)
+{
+    m_trace->WriteTrace("EncryptData","Enter-");
+
+    m_trace->WriteTrace("EncryptData","srcInfo.dwSize = %d",srcInfo.dwSize);
+    m_trace->WriteTrace(CILIXTRACE_L_DEBUG,"EncryptData","srcInfo.data = %s",srcInfo.data);
+
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("EncryptData","设备未打开,不能做GetPinBlock操作");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("EncryptData", "Exit-");
+        return Error_NotInit;
+    }
+
+    if (srcInfo.data == NULL)
+    {
+         m_trace->WriteTrace("EncryptData","EncryptData输入参数srcInfo.data为空");
+         memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+         strcpy(m_Error.szErrMsg,"输入参数为空");
+         m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+         m_trace->WriteTrace("EncryptData", "Exit-");
+         return Error_Null;
+    }
+
+    if (srcInfo.dwSize % 16 !=0 || srcInfo.dwSize % 8 !=0)
+    {
+        m_trace->WriteTrace("EncryptData","EncryptData输入参数srcInfo.dwSize不是8或16的整数倍");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"输入参数错误");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("EncryptData", "Exit-");
+        return Error_Param;
+    }
+
+    //压缩数据
+    unsigned char fswData[1025] = "";
+    CILIX_AUX_X::CILIX_uti_pack((unsigned char*)srcInfo.data, fswData, srcInfo.dwSize);
+
+    int WkSN = 0;
+    if (m_Encryptmethod == 4)
+    {
+        char ReturnInfo[100] = "";
+        int sret = SUNSON_SwitchArithmetic(2, (unsigned char *)ReturnInfo);
+        m_trace->WriteTrace("EncryptData","国密:invoke SUNSON_SwitchArithmetic,sret = %d, ReturnInfo[0] = 0x%02x",sret, ReturnInfo[0]);
+        if (sret != 1)
+        {
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"切换国密算法失败");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+            m_trace->WriteTrace("EncryptData", "Exit-");
+            return Error_DevMedia;
+        }
+
+        if(g_dwWkSN == 99)
+        {
+            WkSN = g_dwMkSN;
+        }
+        else
+        {
+            WkSN = g_dwWkSN + 2;
+        }
+    }
+    else
+    {
+        char ReturnInfo[100] = "";
+        int sret = SUNSON_SwitchArithmetic(0, (unsigned char *)ReturnInfo);
+        m_trace->WriteTrace("EncryptData","非国密:invoke SUNSON_SwitchArithmetic,sret = %d, ReturnInfo[0] = 0x%02x",sret, ReturnInfo[0]);
+        if (sret != 1)
+        {
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"切换非国密算法失败");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+            m_trace->WriteTrace("EncryptData", "Exit-");
+            return Error_DevMedia;
+        }
+
+        if(g_dwWkSN == 99)
+        {
+            WkSN = g_dwMkSN + 10;
+        }
+        else
+        {
+            WkSN = g_dwWkSN + 11;
+        }
+    }
+
+    int mode = 0;
+    if (m_Encryptmethod == 0)
+    {
+        if(m_ECB_CBC_Mode == 1)
+        {
+            mode = 1;
+        }
+        if(m_ECB_CBC_Mode == 2)
+        {
+            mode = 2;
+        }
+    }
+    if (m_Encryptmethod == 1)
+    {
+        if(m_ECB_CBC_Mode == 1)
+        {
+            mode = 0x40;
+        }
+        if(m_ECB_CBC_Mode == 2)
+        {
+            mode = 0x80;
+        }
+    }
+    if (m_Encryptmethod == 4)
+    {
+        if(m_ECB_CBC_Mode == 1)
+        {
+            mode = 0x40;
+        }
+        if(m_ECB_CBC_Mode == 2)
+        {
+            mode = 0x80;
+        }
+    }
+
+    //加密结果
+    BYTE crypt_out[1024*100] = "";
+    char sresult[2050] = "";
+    //计算
+    int sret = SUNSON_DataCompute(WkSN,0x01,mode,0X00,srcInfo.dwSize/2,fswData,(unsigned char*)sresult);
+    m_trace->WriteTrace("EncryptData", "EncryptData操作返回值sret = %d,sresult[0] = 0x%02x",sret,sresult[0]);
+    if (sret > 0)
+    {
+        //拷贝输出结果
+        memcpy(crypt_out, sresult,sret);
+        memset(destInfo.data, 0, 512);
+        CILIX_AUX_X::CILIX_uti_unpack((BYTE*)crypt_out, (BYTE*)destInfo.data, sret);
+        destInfo.dwSize = sret*2;
+        m_trace->WriteTrace("EncryptData", "EncryptData操作成功, destInfo.dwSize=%d",destInfo.dwSize);
+        m_trace->WriteTrace(CILIXTRACE_L_DEBUG, "EncryptData", "destInfo.data = %s",destInfo.data);
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"操作成功");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("EncryptData", "Exit-");
+        return Error_Succeed;
+    }
+    else
+    {
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"加密失败");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("EncryptData", "Exit-");
+        return Error_Hardware;
+    }
+}
+
+ErrorCodeEnum PinPadNantian::MacEncrypt(EnDecryptInfo srcInfo, EnDecryptInfo &destInfo)
+{
+    m_trace->WriteTrace("MacEncrypt","Enter-");
+
+    m_trace->WriteTrace("MacEncrypt","srcInfo.dwSize = %d",srcInfo.dwSize);
+    m_trace->WriteTrace(CILIXTRACE_L_DEBUG,"MacEncrypt","srcInfo.data = %s",srcInfo.data);
+
+    if (m_Open != TRUE)
+    {
+        m_trace->WriteTrace("MacEncrypt","设备未打开,不能做GetMAC操作");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"设备未打开");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("MacEncrypt", "Exit-");
+        return Error_NotInit;
+    }
+
+    if (srcInfo.data == NULL)
+    {
+        m_trace->WriteTrace("MacEncrypt","MacEncrypt输入参数srcInfo.data为空");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"输入参数为空");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("MacEncrypt", "Exit-");
+        return Error_Null;
+    }
+
+    if (srcInfo.dwSize % 16 !=0 || srcInfo.dwSize % 8 !=0)
+    {
+        m_trace->WriteTrace("MacEncrypt","MacEncrypt输入参数srcInfo.dwSize不是8或16的整数倍");
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"输入参数错误");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("MacEncrypt", "Exit-");
+        return Error_Param;
+    }
+
+    //压缩数据
+    unsigned char fswData[1025] = "";
+    CILIX_AUX_X::CILIX_uti_pack((unsigned char*)srcInfo.data, fswData, srcInfo.dwSize);
+
+    int WkSN = 0;
+    if (m_MacAlgorithm == 3)
+    {
+        char ReturnInfo[100] = "";
+        int sret = SUNSON_SwitchArithmetic(2, (unsigned char *)ReturnInfo);
+        m_trace->WriteTrace("MacEncrypt","国密:invoke SUNSON_SwitchArithmetic,sret = %d, ReturnInfo[0] = 0x%02x",sret, ReturnInfo[0]);
+        if (sret != 1)
+        {
+            memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+            strcpy(m_Error.szErrMsg,"切换国密算法失败");
+            m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+            m_trace->WriteTrace("MacEncrypt", "Exit-");
+            return Error_DevMedia;
+        }
+        WkSN = g_dwWkSN + 2;
+    }
+    else
+    {
+        char ReturnInfo[100] = "";
+        int sret = SUNSON_SwitchArithmetic(0, (unsigned char *)ReturnInfo);
+        m_trace->WriteTrace("MacEncrypt","非国密:invoke SUNSON_SwitchArithmetic,sret = %d, ReturnInfo[0] = 0x%02x",sret, ReturnInfo[0]);
+        if (sret != 1)
+        {
+                memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+                strcpy(m_Error.szErrMsg,"切换非国密算法失败");
+                m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+                m_trace->WriteTrace("MacEncrypt", "Exit-");
+                return Error_DevMedia;
+        }
+        WkSN = g_dwWkSN + 11;
+    }
+
+    int mode = 0;
+    if (m_MacAlgorithm == 1)
+    {
+        mode = 0x20;
+    }
+    if (m_MacAlgorithm == 2)
+    {
+        mode = 0x0200;
+    }
+    if (m_MacAlgorithm == 3)
+    {
+        mode = 0x0200;
+    }
+
+    //加密结果
+    BYTE crypt_out[1024*100] = "";
+    char sresult[2050] = "";
+    //计算
+    int sret = SUNSON_MakeMac(WkSN,mode,srcInfo.dwSize/2,fswData,(unsigned char*)sresult);
+    m_trace->WriteTrace("MacEncrypt", "MacEncrypt操作返回值sret = %d,sresult[0] = 0x%02x",sret,sresult[0]);
+    if (sret > 0)
+    {
+        //拷贝输出结果
+        memcpy(crypt_out, sresult,sret);
+        memset(destInfo.data, 0, 512);
+        CILIX_AUX_X::CILIX_uti_unpack((BYTE*)crypt_out, (BYTE*)destInfo.data, sret);
+        destInfo.dwSize = sret*2;
+        m_trace->WriteTrace("EncryptData", "MacEncrypt操作成功,destInfo.dwSize=%d",destInfo.dwSize);
+        m_trace->WriteTrace(CILIXTRACE_L_DEBUG, "EncryptData", "destInfo.data = %s",destInfo.data);
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"操作成功");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("MacEncrypt", "Exit-");
+        return Error_Succeed;
+    }
+    else
+    {
+        memset(m_Error.szErrMsg,0,sizeof(m_Error.szErrMsg));
+        strcpy(m_Error.szErrMsg,"加密失败");
+        m_Error.dwErrMsgLen = strlen(m_Error.szErrMsg);
+
+        m_trace->WriteTrace("MacEncrypt", "Exit-");
+        return Error_Hardware;
+    }
+}
+
+int PinPadNantian::GetEncryptFunc()
+{
+    return 3;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 66 - 0
DevAdapter/nantian/pinpad.1.1/pinpad.nantian.1.1.h

@@ -0,0 +1,66 @@
+
+#include "../include/PinPadClass.h"
+//#include "../include/log4vendor.h"
+#include "CILIX_AUX_UTILS.h"
+
+class PinPadNantian : public PinPadClass
+{
+public:
+    PinPadNantian();
+    ~PinPadNantian();
+
+    //DeviceBaseClass
+    ErrorCodeEnum GetDevCategory(DevCategoryInfo &devCategory);
+    ErrorCodeEnum Reset();
+    ErrorCodeEnum DevClose();
+    ErrorCodeEnum GetLastErr(DevErrorInfo &devErrInfo);
+
+    //PinPadClass
+    ErrorCodeEnum DevOpen(DWORD dwPort, DWORD dwBaudRate);
+    ErrorCodeEnum KeyRead(BYTE &ch);
+    ErrorCodeEnum SetParam(SetParamTypeEnum eType, SetParamValueEnum eValue);
+    ErrorCodeEnum SetAccNo(AccountInfo accInfo);
+    ErrorCodeEnum LoadMasterKey(MasterKeyParam masterKey);
+    ErrorCodeEnum LoadWorkingKey(WorkKeyParam wkKey);
+    ErrorCodeEnum ActiveWorkingKey(DWORD dwMkSN, DWORD dwWkSN);
+    ErrorCodeEnum StartPinInput(BYTE byLen);
+    ErrorCodeEnum StartPinInputConfirm(BYTE byLen);
+    ErrorCodeEnum StartPlainInput();
+    ErrorCodeEnum StopInput();
+    ErrorCodeEnum GetPinBlock(PinBlock &block);
+    ErrorCodeEnum EncryptData(EnDecryptInfo srcInfo, EnDecryptInfo &destInfo);
+    ErrorCodeEnum MacEncrypt(EnDecryptInfo srcInfo, EnDecryptInfo &destInfo);
+    int GetEncryptFunc();
+    
+    BOOL m_Open;            //标志设备是否打开
+    DevErrorInfo m_Error;   //标记错误码
+    int g_flag;             //标记按键输入模式
+    int m_PinNum;           //记录密码输入个数
+    int g_Auto;             //标记是否自动结束
+    AccountInfo g_CardNo;   //存储CustomData的数据
+    DWORD g_dwMkSN;         //标记主密钥号
+    DWORD g_dwWkSN;         //标记工作秘钥号
+	
+    int (*SUNSON_OpenCom)(const char *sztty, long nBaudrate);
+    int (*SUNSON_GetVersionNo)(unsigned char *VersionNo);
+    int (*SUNSON_CloseCom)(void);
+    int (*SUNSON_ScanGetKey)(unsigned char *ucKeyValue);
+    int (*SUNSON_CloseEppPlainTextMode)(unsigned char *ReturnInfo);
+    int (*SUNSON_LoadSM4Key)(int ucKeyId,int ucDecryptKeyId,int KeyAttribute,unsigned char ucKeyLen,unsigned char *KeyValue,
+    unsigned char *ReturnInfo);
+    int (*SUNSON_LoadUserKey)(int ucKeyId, int ucDecryptKeyId, long KeyAttribute,unsigned char ucKeyLen, unsigned char *KeyValue,
+    unsigned char *ReturnInfo);
+    int (*SUNSON_SetKeyMark)(long ActiveFunc, long ActiveFDK, long EndFunc, long EndFDK, unsigned char*ReturnInfo);
+    int (*SUNSON_GetPin)(unsigned char ucPinMinLen, unsigned char ucPinMaxLen, unsigned char AutoReturnFlag, unsigned char *ReturnInfo);
+    int (*SUNSON_UseEppPlainTextMode)(unsigned char PlaintextLength, unsigned char AutoEnd, unsigned char *ReturnInfo);
+    int (*SUNSON_SwitchArithmetic)(unsigned char ArithmeticType,unsigned char *DataResult);
+    int (*SUNSON_GetPinBlock)(int UserKeyId, int JM_mode, unsigned char padchar, unsigned char ucCardLen, unsigned char*ucCardNumber,
+    unsigned char*PinBlockResult);
+    int (*SUNSON_DataCompute)(int KeyId, unsigned char JM_mode, int SF_mode, unsigned char padchar, int datalen, unsigned char *data, 
+    unsigned char *DataResult);
+    int (*SUNSON_MakeMac)(int UserKeyId, int Mac_mode, int nMacDataLen, unsigned char *ucMacData, unsigned char *MacResult);
+    int (*SUNSON_ScanKeyPress)(unsigned char *ucKeyValue);
+    
+};
+
+