#include "stdafx.h" #include "ContactlessFSM.h" #include "EventCode.h" #include "GetDevInfoHelper.h" #include "ContactlessCard_msg_g.h" #include "ModuleMix.h" #include "ContactlessCard_UserErrorCode.h" #include "CommDevEntityErrorCode.h" const int GET_DEV_STATUS_COUNT = 3; const int MAX_RESET_TIMES_PERIOD = 1000;//oiltest configure to ini file? const int MAX_RESET_TIMEROUT = 5000; const int WAIT_TRY_NUM = 120; const int WAIT_INTERVAL = 500; const int ACCEPT_TRY_INTERVAL = 500; const int ACCEPT_TRY_NUM = 110; const int READ_TRY_NUM = 1;//oiltest const int INIT_TRY_NUM = 3; class CContactlessCardEntity; void CContactlessCardFSM::s0_on_entry() { LOG_FUNCTION(); m_eDevState = DEVICE_STATUS_NOT_READY; FSMEvent *e = new FSMEvent(USER_EVT_INIT); PostEventFIFO(e); } void CContactlessCardFSM::s0_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s0_on_event(FSMEvent* e) { LOG_FUNCTION(); if (e->iEvt == USER_EVT_INIT) { InitTask* task = new InitTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(task); e->SetHandled(); return 0; }else if (e->iEvt == USER_EVT_QUIT) { e->SetHandled(); return 0; } return 0; } void CContactlessCardFSM::s1_on_entry() { LOG_FUNCTION(); } void CContactlessCardFSM::s1_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s1_on_event(FSMEvent* event) { LOG_FUNCTION(); if (event->iEvt == USER_EVT_INITFINISHED) { event->SetHandled(); int err = event->param1; if (err == 0) { return 0; } else { return 1; } }else if (event->iEvt == USER_EVT_QUIT) { event->SetHandled(); return 0; } return 0; } //Idle void CContactlessCardFSM::s2_on_entry() { LOG_FUNCTION(); GetEntityBase()->GetFunction()->SetUserDefineState(USER_CONTACTLESSCARD_IDLE); m_eDevState = DEVICE_STATUS_NORMAL; Dbg("set reset times 0."); m_resetTimes = 0; m_testResult = Error_Succeed; } void CContactlessCardFSM::s2_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s2_on_event(FSMEvent* pEvt) { Dbg("s2 evt(%d)",pEvt->iEvt); int ret = 0; switch(pEvt->iEvt) { case USER_EVT_ACCEPT: { CardAcceptEvent *cae = dynamic_cast(pEvt); m_bCancelAccept = false; AcceptTask* task = new AcceptTask(this); task->ctx = cae->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); } break; case USER_EVT_QUERY_CARD_INFO: { pEvt->SetHandled(); QueryCardInfoEvent *pQCIE = dynamic_cast(pEvt); QueryCardInfoTask* task = new QueryCardInfoTask(this); task->ctx = pQCIE->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_EJECT: { CardEjectEvent *cee; if (pEvt->iEvt == USER_EVT_EJECT) cee = dynamic_cast(pEvt); EjectTask *task= new EjectTask(this); if (pEvt->iEvt == USER_EVT_EJECT) task->ctx = cee->ctx; else task->ctx = NULL; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); return 0; } case USER_EVT_EXIT: m_bExit = true; pEvt->SetHandled(); break; case USER_EVT_QUIT: pEvt->SetHandled(); break; default: break; } return ret; } //accepting void CContactlessCardFSM::s3_on_entry() { LOG_FUNCTION(); } void CContactlessCardFSM::s3_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s3_on_event(FSMEvent* pEvt) { Dbg("s3 evt(%d)(%d)",pEvt->iEvt,pEvt->param1); int ret = 0; switch(pEvt->iEvt) { case USER_EVT_ACCEPTFINISHED: { pEvt->SetHandled(); switch(pEvt->param1) { case 0: case 1: case 2: case 3: case 4: ret = pEvt->param1; break; default: ret = 1; break; } } break; case USER_EVT_ACCEPT_CANCEL: m_bCancelAccept = true; pEvt->SetHandled(); ret = 3; break; case USER_EVT_QUERY_CARD_INFO: { pEvt->SetHandled(); QueryCardInfoEvent *pQCIE = dynamic_cast(pEvt); QueryCardInfoTask* task = new QueryCardInfoTask(this); task->ctx = pQCIE->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_EXIT: m_bExit = true; pEvt->SetHandled(); break; case USER_EVT_QUIT: pEvt->SetHandled(); break; default: break; } return ret; } //Hold void CContactlessCardFSM::s4_on_entry() { LOG_FUNCTION(); GetEntityBase()->GetFunction()->SetUserDefineState(USER_CONTACTLESSCARD_HOLD); } void CContactlessCardFSM::s4_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s4_on_event(FSMEvent* pEvt) { Dbg("s4 evt(%d,%d)",pEvt->iEvt,pEvt->param1); switch(pEvt->iEvt){ case USER_EVT_ACCEPT: { CardAcceptEvent *cae = dynamic_cast(pEvt); m_bCancelAccept = false; AcceptTask* task = new AcceptTask(this); task->ctx = cae->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); } break; case USER_EVT_PREONLINE: { PreOnlineEvent* poe = dynamic_cast(pEvt); PreOnlineTask* task = new PreOnlineTask(this); task->ctx = poe->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); return 0; } case USER_EVT_POSTONLINE: { PostOnlineEvent* poe = dynamic_cast(pEvt); PostOnlineTask* task = new PostOnlineTask(this); task->ctx = poe->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); return 0; } case USER_EVT_EXIT: case USER_EVT_EJECT: //case USER_EVT_ACCEPT: { pEvt->SetHandled(); //if (pEvt->iEvt == USER_EVT_ACCEPT) //{ // CardAcceptEvent *pCAE = dynamic_cast(pEvt); // pCAE->ctx->Answer(Error_Duplication); // return 0; //} //if ((pEvt->iEvt == USER_EVT_EXIT) && m_bIssued) //{ // return 1; //} CardEjectEvent *cee; if (pEvt->iEvt == USER_EVT_EJECT) cee = dynamic_cast(pEvt); EjectTask *task= new EjectTask(this); if (pEvt->iEvt == USER_EVT_EJECT) task->ctx = cee->ctx; else task->ctx = NULL; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_QUERY_CARD_INFO: { pEvt->SetHandled(); QueryCardInfoEvent *pQCIE = dynamic_cast(pEvt); QueryCardInfoTask* task = new QueryCardInfoTask(this); task->ctx = pQCIE->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_QUERY_CARD_INFO_FINISHED: { pEvt->SetHandled(); if (pEvt->param1 == 0) return 0; else return 1; } case USER_EVT_QUIT: { pEvt->SetHandled(); return 0; } default: break; } return 0; } //Reading void CContactlessCardFSM::s5_on_entry() { LOG_FUNCTION(); GetEntityBase()->GetFunction()->SetUserDefineState(USER_CONTACTLESSCARD_READING); } void CContactlessCardFSM::s5_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s5_on_event(FSMEvent* pEvt) { Dbg("s5 event(%d)",pEvt->iEvt); switch(pEvt->iEvt) { //case USER_EVT_READFINISHED: // { // pEvt->SetHandled(); // CardReadFinishedEvent *pCRFE = dynamic_cast(pEvt); // int err = pCRFE->param1; // Dbg("readfinish(%d)",err); // if (err == 0) // { // pCRFE->ctx->Answer(Error_Succeed); // return 0; // }else if (err == 2) // return 2; // else // return 1; // } // break; //case USER_EVT_READ_FINISHED: // { // pEvt->SetHandled(); // CardReadFinishedEvent *pCRFE = dynamic_cast(pEvt); // int err = pCRFE->param1; // Dbg("read finish(%d)",err); // if (err == 0) // { // pCRFE->ctx->Answer(Error_Succeed); // return 0; // }else if (err == 2) // return 2; // else // { // pCRFE->ctx->Answer(Error_Unexpect); // return 1; // } // } // break; case USER_EVT_EXIT: { //CardEjectEvent *cee = dynamic_cast(pEvt); EjectTask *task= new EjectTask(this); task->ctx = NULL; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); return 0; } break; case USER_EVT_QUIT: { pEvt->SetHandled(); return 0; } default: break; } return 0; } //Ejecting void CContactlessCardFSM::s6_on_entry() { LOG_FUNCTION(); } void CContactlessCardFSM::s6_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s6_on_event(FSMEvent* pEvt) { Dbg("s6 evt(%d,%d)",pEvt->iEvt,pEvt->param1); int ret = 0; switch(pEvt->iEvt) { case USER_EVT_EJECTFINISHED: pEvt->SetHandled(); ret = pEvt->param1; break; case USER_EVT_QUIT: case USER_EVT_EXIT: pEvt->SetHandled(); break; default: break; } return ret; } void CContactlessCardFSM::s7_on_entry() { LOG_FUNCTION(); GetEntityBase()->GetFunction()->SetUserDefineState(USER_CONTACTLESSCARD_WAITFETCHING); WaitFetchingTask* task = new WaitFetchingTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(task); } void CContactlessCardFSM::s7_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s7_on_event(FSMEvent* pEvt) { Dbg("s7 evt(%d)",pEvt->iEvt); switch(pEvt->iEvt) { case USER_EVT_WAITFINISHED: { pEvt->SetHandled(); if (pEvt->param1 == 0) { FetchCard evt; evt.status = 0; SpSendBroadcast(m_pEntity->GetFunction(),SP_MSG_OF(FetchCard),SP_MSG_SIG_OF(FetchCard),evt); LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_OP,"CardIssuer op."); Dbg("客户取走卡片msg发送"); return 0; } else if (pEvt->param1 == 1) { //FetchCard evt; //evt.status = 1; //SpSendBroadcast(m_pEntity->GetFunction(),SP_MSG_OF(FetchCard),SP_MSG_SIG_OF(FetchCard),evt); //Dbg("取卡时设备故障"); //return 1; } else { FetchCard evt; evt.status = 2; SpSendBroadcast(m_pEntity->GetFunction(),SP_MSG_OF(FetchCard),SP_MSG_SIG_OF(FetchCard),evt); Dbg("客户未取卡超时msg发送"); LogWarn(Severity_Low,Error_NotInit,LOG_WARN_CONTACTLESS_CARD_FORGET_FETCH,"Customer forget fetch card."); return 2; } } case USER_EVT_QUERY_CARD_INFO: { pEvt->SetHandled(); QueryCardInfoEvent *pQCIE = dynamic_cast(pEvt); QueryCardInfoTask* task = new QueryCardInfoTask(this); task->ctx = pQCIE->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_QUIT: { pEvt->SetHandled(); return 0; } default: break; } return 0; } //capture void CContactlessCardFSM::s8_on_entry() { LOG_FUNCTION(); } void CContactlessCardFSM::s8_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s8_on_event(FSMEvent* pEvt) { Dbg("s8 evt(%d)",pEvt->iEvt); if (pEvt->iEvt == USER_EVT_CAPTUREFINISHED){ pEvt->SetHandled(); int err = pEvt->param1; if (err == 0) return 0; else return 1; }else if (pEvt->iEvt == USER_EVT_QUIT) { pEvt->SetHandled(); return 0; } return 0; } void CContactlessCardFSM::s9_on_entry() { LOG_FUNCTION(); GetEntityBase()->GetFunction()->SetUserDefineState(USER_CONTACTLESSCARD_FAILED); m_eDevState = DEVICE_STATUS_FAULT; FSMEvent *e = new FSMEvent(USER_EVT_RESET); PostEventFIFO(e); LogWarn(Severity_High,Error_NotInit,LOG_ERR_CONTACTLESS_CARD_FAILED,"Contactless card s9 failed."); } void CContactlessCardFSM::s9_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s9_on_event(FSMEvent* pEvt) { Dbg("s9 evt(%d)",pEvt->iEvt); switch(pEvt->iEvt) { case USER_EVT_RESET: { pEvt->SetHandled(); m_resetTimes++; if (m_resetTimes > MAX_RESET_TIMES_PERIOD) { Dbg("restart tried %d times,give up",m_resetTimes); m_testResult = Error_InvalidState; LogWarn(Severity_Low,Error_Unexpect, ContactlessCard_UserErrorCode_Reset_Failed,GetEntityBase()->GetEntityName()); return 0; } ResetDeviceEvent* rde = dynamic_cast(pEvt); ResetTask* task = new ResetTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } break; case USER_EVT_RESETFINISHED: { ResetFinishedEvent *rfe = dynamic_cast(pEvt); Dbg("err,reset result %d",rfe->param1); return rfe->param1; } case USER_EVT_QUERY_CARD_INFO: { pEvt->SetHandled(); QueryCardInfoEvent *pQCIE = dynamic_cast(pEvt); QueryCardInfoTask* task = new QueryCardInfoTask(this); task->ctx = pQCIE->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_QUIT: pEvt->SetHandled(); return 0; case USER_EVT_ACCEPT_CANCEL: m_bCancelAccept = true; pEvt->SetHandled(); break; default: break; } return 0; } ErrorCodeEnum CContactlessCardFSM::OnInit() { LOG_FUNCTION(); /*------2020-02-27------*/ //modify by LZM VendorLogControler(this,"ContactlessCard"); /*---------------------*/ m_pCardProcess = new CCardProcess(); if (m_pCardProcess == NULL)//almost no use... { Dbg("create card process failed."); return Error_Resource; } ErrorCodeEnum errCode = Load(); if (errCode != Error_Succeed) { Dbg("Load failed(%d).",errCode); return errCode; } devStatus.eMediaPos = CI_MEDIA_NOTPRESENT; return Error_Succeed; } ErrorCodeEnum CContactlessCardFSM::OnExit() { LOG_FUNCTION(); ErrorCodeEnum eExit; if (m_pRFIC != NULL) { eExit = m_pRFIC->GetDevStatus(devStatus); if (eExit == Error_Succeed) { if (devStatus.eMediaPos == CI_MEDIA_PRESENT){ } } eExit = m_pRFIC->DevClose(); if (eExit == Error_Succeed) Dbg("读卡器关闭成功"); else Dbg("读卡器关闭失败(%d)",eExit); } FSMImpl::OnExit(); return Error_Succeed; } ErrorCodeEnum CContactlessCardFSM::Load() { // MessageBoxA(0,0,0,0); LOG_FUNCTION(); HRESULT hr; int initTries = 0; bool bClosePort = false; ErrorCodeEnum eErrDev; CSimpleStringA dllName; eErrDev = SpGetDevAdaptorPath(m_pEntity,GetEntityBase()->GetEntityName(),dllName); if (eErrDev != Error_Succeed) { Dbg("load vendor dll(%s) failed.",(LPCTSTR)dllName); return Error_DevLoadFileFailed; } Dbg("%s",(LPCTSTR)dllName); CSmartPointer spEntityFunction = GetEntityBase()->GetFunction(); CSmartPointer spConfig; eErrDev = spEntityFunction->OpenConfig(Config_Root, spConfig); if (eErrDev != Error_Succeed) { Dbg("open cfg file failed!"); return eErrDev; } CSimpleStringA csBinPath,csBackslash("\\"); ErrorCodeEnum eErrPath = GetEntityBase()->GetFunction()->GetPath("Bin", csBinPath); if (eErrPath != Error_Succeed) { Dbg("GetBasePath failed (%d).",eErrPath); return Error_Param; } m_hVerdorDll = LoadLibraryA(dllName); if (m_hVerdorDll == NULL) { Dbg("Load dll failed.%d",GetLastError()); return Error_DevLoadFileFailed; } if ((CreateDevComponent = (lpCreateDevCom)GetProcAddress(m_hVerdorDll,"CreateDevComponent")) == NULL) { Dbg("Get CreateDevComponent failed."); return Error_DevLoadFileFailed; } if ((ReleaseDevComponent = (lpReleaseDevCom)GetProcAddress(m_hVerdorDll,"ReleaseDevComponent")) == NULL) { Dbg("Get ReleaseDevComponent failed."); return Error_DevLoadFileFailed; } do{ if (m_pRFIC == NULL) { if (CreateDevComponent((DeviceBaseClass *&)m_pRFIC) != Error_Succeed) { LOG_TRACE("创建读卡器设备模块失败"); initTries++; continue; } } // CardIssuerInitParam ciInitParam; int baudRate,port,smflag,onlineOnly; spConfig->ReadConfigValueInt("Device.ContactlessCard","Baudrate",baudRate); spConfig->ReadConfigValueInt("Device.ContactlessCard","Port",port); spConfig->ReadConfigValueInt("Device.Utility","SMSupport",smflag); spConfig->ReadConfigValueInt("Device.Utility","OnlineOnly",onlineOnly); m_bSM = smflag; m_bOnlineOnly = onlineOnly; Dbg("open card issuer [%d][%d]",port,baudRate); hr = m_pRFIC->DevOpen(port,baudRate); Dbg("open[%d]",hr); if (hr == Error_Succeed) { bClosePort = true; LOG_TRACE("读卡器打开成功"); //hr = m_pRFIC->Reset(); //Dbg("cardreader reset(%d)",hr); //if (hr != Error_Succeed) //{ // DevErrorInfo devErrInfo; // m_pRFIC->GetLastErr(devErrInfo); // Dbg("reset err[%s]",devErrInfo.szErrMsg); //} CSimpleStringA csCMBPrint("CMBPrint.dll"); csCMBPrint = csBinPath + csBackslash + csCMBPrint; Dbg("cmbpath %s",(LPCTSTR)csCMBPrint); HMODULE hr = LoadLibraryA(csCMBPrint); if (hr == NULL) { Dbg("Load CMBPrint failed(%d).",hr); return Error_DevLoadFileFailed; } if ((cmdDecodeMag2=(lpCMBdecodeMag2)GetProcAddress(hr, "CMBdecodeMag2")) == NULL) { Dbg("Get Mag2 address failed."); return Error_DevLoadFileFailed; } if ((cmdDecodeEx=(lpCMBdecodeEx)GetProcAddress(hr, "CMBdecodeEx")) == NULL) { Dbg("Get Mag23Ex address failed."); return Error_DevLoadFileFailed; } initTries = 0; break; } else { DevErrorInfo devErrInfo; m_pRFIC->GetLastErr(devErrInfo); Dbg("%s",devErrInfo.szErrMsg); Dbg("读卡器 DevOpen (%d)",hr); initTries++; } }while(initTries < INIT_TRY_NUM); Dbg("inittries[%d]",initTries); if (initTries != 0) { if (bClosePort) m_pRFIC->DevClose(); LOG_TRACE("读卡器打开失败"); return Error_DevCommFailed; } else { eErrDev = spEntityFunction->OpenConfig(Config_Run, spConfig); if (eErrDev != Error_Succeed) { Dbg("open run cfg file failed!"); return eErrDev; } int ret = 0,isIssue = 0; if ((spConfig->ReadConfigValueInt("RunInfo","CardRemains",m_CardRemains) == Error_Succeed) && (spConfig->ReadConfigValueInt("RunInfo","CardIssued",m_CardIssued) == Error_Succeed) && (spConfig->ReadConfigValueInt("RunInfo","CardCaptured",m_CardCaptured) == Error_Succeed) && (spConfig->ReadConfigValueInt("RunInfo","IsIssue",isIssue) == Error_Succeed) && (spConfig->ReadConfigValueInt("RunInfo","CardMixed",m_CardMixed) == Error_Succeed) && (spConfig->ReadConfigValueInt("RunInfo","CardInit",m_CardInit) == Error_Succeed) && (spConfig->ReadConfigValueInt("RunInfo","CardPercent",m_CardPercent) == Error_Succeed)) { Dbg("in %d cycle",isIssue); m_bIssued = isIssue; //ret = UnAcceptCard(); } else return Error_IO; if (ret == 0) { //m_pGUIConsoleClient = new GUIConsoleService_ClientBase(dynamic_cast(GetEntityBase())); //ErrorCodeEnum eConn = m_pGUIConsoleClient->Connect(); //if (eConn != Error_Succeed) //{ // m_pGUIConsoleClient->SafeDelete(); // m_pGUIConsoleClient = NULL; //} //else // Dbg("GUIConsole connected."); return Error_Succeed; } else return Error_Unexpect; } } int CContactlessCardFSM::Initial() { return 0; } bool CContactlessCardFSM::GetDevStatus() { //LOG_FUNCTION(); int getDevInfoCount = 0; ErrorCodeEnum err; do{ err = m_pRFIC->GetDevStatus(devStatus); if (Error_Succeed == err) return true; else { //if (Reset()) // continue; //Dbg("GetDevStatus failed(%d).",hr); DevErrorInfo devErrInfo; m_pRFIC->GetLastErr(devErrInfo); Dbg("GetDevStatus:[%s]",devErrInfo.szErrMsg); getDevInfoCount++; Sleep(3000); } } while (getDevInfoCount < GET_DEV_STATUS_COUNT); Dbg("getdevstatus to reset"); err = m_pRFIC->Reset(); Sleep(MAX_RESET_TIMEROUT); if (err == Error_Succeed) { err = m_pRFIC->GetDevStatus(devStatus); if (err == Error_Succeed && devStatus.eMediaPos == CI_MEDIA_PRESENT) { } } return false; } int CContactlessCardFSM::Reset() { LOG_FUNCTION(); ErrorCodeEnum eErr; eErr = m_pRFIC->Reset(); if (eErr == Error_Succeed) { if (Error_Succeed == m_pRFIC->GetDevStatus(devStatus)) { Dbg("media position %d",devStatus.eMediaPos); return 0; } else return 2; } else { Dbg("reset not succeed %d",eErr); return 1; } } int CContactlessCardFSM::InternalAcceptCard() { LOG_FUNCTION(); ErrorCodeEnum eErr; int acceptTries = 0, err = 0; m_bWaitingAccept = true; //if (Error_Succeed == hr){ do { if (m_bExit) { m_bCancelAccept = true; break; } if (m_bCancelAccept) { err = 3; goto Err; } if (m_bWaitAccepteMore) { acceptTries = 0; m_bWaitAccepteMore = false; } if (GetDevStatus()) { Dbg("oiltest %d",devStatus.eMediaPos); if (devStatus.eMediaPos == CI_MEDIA_RF) { LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_OP,"Contactless card op."); acceptTries = 0; goto Err; } else { acceptTries++; Sleep(ACCEPT_TRY_INTERVAL); } } else { err = 1; goto Err; } }while (acceptTries < ACCEPT_TRY_NUM); err = 2; Err: m_bExit = false; m_bWaitingAccept = false; if (m_bCancelAccept && err != 1) { if (GetDevStatus()) { if (devStatus.eMediaPos == CI_MEDIA_PRESENT) { err = 4; Dbg("cancel eject......"); } } else err = 2; } return err; } int FindHexCharPosition(LPBYTE data, BYTE hexChar, int len) { int notExist = -1,ret = 1,pos = 0; for (; pos < len; ++pos) { BYTE high = (*(data+pos))&0xf0; BYTE low = (*(data+pos))&0x0f; if ((high>>4) != hexChar) ret++; else return ret; if (low != hexChar) ret++; else return ret; } ret = notExist; return ret; } int CContactlessCardFSM::AcceptCard(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); ctx->Ans.ICType = 0; m_pCardProcess->DataInit(); LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_ON,"ContactCard green on"); m_bWaitAccepteMore = false; //GpioService_Set_Req Req; //GpioService_Set_Ans Ans; //Req.devseq = CARDREADER; //Req.mode = 1; //Req.close = 0; //CCardReaderEntity* pEntity = dynamic_cast(m_pEntity); //pEntity->SetGpio(Req,Ans); int rc = InternalAcceptCard(); //Req.devseq = CARDREADER; //Req.mode = 1; //Req.close = 1; //pEntity->SetGpio(Req,Ans); LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_OFF,"ContactCard green off"); if (rc == 0) { //FSMSetIssueFlag(false); if (ctx != NULL) { Dbg("insert error_succeed"); FetchCard evt; evt.status = 3;//oilyang@20181210 用于通知CardIssuer取消插卡 SpSendBroadcast(m_pEntity->GetFunction(), SP_MSG_OF(FetchCard), SP_MSG_SIG_OF(FetchCard), evt); ctx->Ans.ICData = ""; int activeCardType; bool bGetICData = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_RFIC, m_pRFIC, "A000000333", activeCardType); if (!bGetICData) { Dbg("DetectAndReadICData failed."); ctx->Answer(Error_Unexpect); return 1; } ctx->Ans.t2Account = ctx->Ans.ICData = ""; ICData track2(false,0x57,0x00); ErrorCodeEnum eErr = Error_Unexpect; string t2ICAccount(""),t2ICCardSerial(""),t2ICCVC(""),t2ICTrack2(""),cardType; if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC,track2,false,0) == -1) { Dbg("[ic]no track2 data"); eErr = m_pRFIC->HaltCard(); ctx->Answer(Error_Unexpect);//can't find track2,retry 20150128 } else { int pos = FindHexCharPosition(track2.value, 0x0d, track2.lenth); char *pICTrack2 = new char[128]; ZeroMemory(pICTrack2, 128); HexBuf2StrBuf(track2.value, &pICTrack2, track2.lenth); pICTrack2[37] = '\0'; char *ddd = new char[128]; memset(ddd, 0, 128); memcpy(ddd, pICTrack2, pos - 1); t2ICTrack2 = pICTrack2; t2ICAccount = (char*)ddd;//oiltest Dbg("contactless card countcount:%s,%s", t2ICAccount.substr(0, 6).c_str(), t2ICAccount.substr(t2ICAccount.length() - 4, 4).c_str()); ctx->Ans.ICData = ctx->Ans.t2Account = t2ICAccount.c_str(); ctx->Ans.ICType = 4; ctx->Ans.status = 0; delete[]ddd; delete[]pICTrack2; //m_pRFIC->DeactContactlessICCard(); } ctx->Answer(Error_Succeed); } } else if(rc == 2) { if (ctx != NULL) ctx->Answer(Error_TimeOut); } else if(rc == 3 || rc == 4) { if (ctx != NULL) { Dbg("insert cancel (%d)",rc); ctx->Answer(Error_Cancel); } }else { if (ctx != NULL) ctx->Answer(Error_Unexpect); } return rc; } static CSimpleStringA GetStrData(TrackInfo trackInfo) { //LOG_FUNCTION(); CSimpleStringA strRet; switch (trackInfo.eStatus) { case CI_DATA_OK: strRet = (char*)trackInfo.data; break; case CI_DATA_INVALID: strRet = "无效数据"; break; //case CI_DATA_MISSING: default: strRet = "数据丢失"; } return strRet; } int CContactlessCardFSM::SplitTrack2(CSimpleStringA pTrack2,Track2Data &decodeData) { if (pTrack2.GetLength() == 0) return -1; int dataLen = strlen(pTrack2); switch(dataLen) { case 28: decodeData.t2Region = CSimpleString(pTrack2,4); decodeData.t2Account = pTrack2.SubString(4,8); decodeData.t2CardSerial = pTrack2.SubString(14,8);//oilyang for 8 onecard decodeData.t2CVC = pTrack2.SubString(22,6); decodeData.t2ExpireDate = ""; break; case 31: decodeData.t2Account = CSimpleString(pTrack2,16); decodeData.t2CardSerial = pTrack2.SubString(16,1); decodeData.t2CVC = pTrack2.SubString(17,6); decodeData.t2Region = pTrack2.SubString(23,4); decodeData.t2ExpireDate = pTrack2.SubString(27,4); break; case 38: break; default: return -1; } decodeData.status = 0; return 0; } int CContactlessCardFSM::PreOnline(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); m_pCardProcess->DataInit(); Dbg("bus data[%s]",(LPCTSTR)ctx->Req.businessData); m_pCardProcess->SplitBusinessData(ctx->Req.businessData,ctx->Req.businessData.GetLength()); if (m_bSM) { Dbg("We support sm."); m_pCardProcess->SplitBusinessData("DF690101",strlen("DF690101")); } int activeCardType; if (!m_pCardProcess->DetectAndReadICData(CARD_MACHINE_RFIC, m_pRFIC, "A000000333", activeCardType))//oiltest 20140915 { ctx->Answer(Error_Unexpect); return 0; } //if (m_cardType == CI_CARDTYPE_IC) //{ // ProcessRestrict(); // CardholderVerify(); m_pCardProcess->TermRiskManage(); CSimpleStringA taaResult; BYTE bt9f27 = 0; int retTAA = m_pCardProcess->TermActionAnalyze(CARD_MACHINE_RFIC,m_pRFIC,taaResult,m_bOnlineOnly,m_bCDA,bt9f27); Dbg("TermActionAnalyze %d",retTAA); switch(retTAA) {//to be added oiltest 20140929 case -1: //some data may be wrong break; case 1: //terminal trans break; case 2: //to do trans end "TransEnd" break; default: break; } ctx->Ans.result = taaResult; // Dbg("[%d,%d,%d,%d]",m_TVR[0],m_TVR[1],m_TVR[2],m_TVR[3]); //} if (ctx->Ans.result.GetLength() == 0) { ctx->Answer(Error_Succeed); return 0; } Dbg("term action analyze result[%s]",(const char*)ctx->Ans.result); //char tmpResult[1024,]result[1024]; //ZeroMemory(tmpResult,sizeof(tmpResult)); //ZeroMemory(result,sizeof(result)); //memcpy(tmpResult,ctx->Ans.result,ctx->Ans.result.GetLength()); string tmpResult, actionType, result = "", baseICData = ""; tmpResult = ctx->Ans.result; char *pSomeICData = new char[1024]; ZeroMemory(pSomeICData, 1024); int lenRet = m_pCardProcess->ConstructARQCData(tmpResult.substr(6, 4).c_str(), m_pDataToARQC, pSomeICData); baseICData = pSomeICData; if (pSomeICData != NULL) delete[]pSomeICData; char arqcLen[8]; ZeroMemory(arqcLen,sizeof(arqcLen)); itoa(lenRet,arqcLen,10); ICData appExpiryDate(false,0x5f,0x24); if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC,appExpiryDate,false,0) == -1) { Dbg("can't find expire date"); return 0; } char *pExpireDate = new char[12]; ZeroMemory(pExpireDate,12); HexBuf2StrBuf(appExpiryDate.value,&pExpireDate,appExpiryDate.lenth); ICData track2(false,0x57,0x00),ICCardSerial(false,0x5f,0x34); ErrorCodeEnum eErr = Error_Unexpect; string t2ICAccount(""),t2ICCardSerial(""),t2ICCVC(""),t2ICTrack2(""),cardType("0"); char *pICCardSerial = new char[4]; ZeroMemory(pICCardSerial,4); if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC,ICCardSerial,false) == -1) { Dbg("can't find card serial."); } else { HexBuf2StrBuf(ICCardSerial.value,&pICCardSerial,ICCardSerial.lenth); } if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC,track2,false,0) == -1) { Dbg("[ic]no track2 data"); //eErr = m_pRFIC->ReleaseIC(); Dbg("ic failed,release it %d",eErr); } else { int pos = FindHexCharPosition(track2.value,0x0d,track2.lenth); char *pICTrack2 = new char[128]; ZeroMemory(pICTrack2,128); HexBuf2StrBuf(track2.value,&pICTrack2,track2.lenth); pICTrack2[37] = '\0'; Dbg("ic.track2,pos:%d",pos); char *ddd = new char[40]; ZeroMemory(ddd,40); memcpy(ddd,pICTrack2,pos-1); char icTrack2Data[128]; ZeroMemory(icTrack2Data,sizeof(icTrack2Data)); Track2Data track2Data; track2Data.status = 0; track2Data.t2Account = ""; cmdDecodeMag2(pICTrack2,icTrack2Data); if (SplitTrack2(icTrack2Data,track2Data) == 0) { t2ICAccount = track2Data.t2Account; //t2ICCardSerial = track2Data.t2CardSerial; t2ICCVC = track2Data.t2CVC; t2ICTrack2 = pICTrack2; Dbg("done(ic)."); } //} if (strnicmp(track2Data.t2Account,ddd,strlen(ddd))) { t2ICCVC = ""; t2ICTrack2 = pICTrack2; t2ICAccount = (char*)ddd; Dbg("contactless card countcount:%s,%s", t2ICAccount.substr(0, 6).c_str(), t2ICAccount.substr(t2ICAccount.length() - 4, 4).c_str()); } t2ICCardSerial = pICCardSerial; delete []ddd; delete []pICTrack2; } //80 1e 80 0008 328ab54bfc986b85 07010103a0b000010a010000000000754048769000 if (m_pCardProcess->GetP1() == 0x1) actionType = "ARQC"; else actionType = ""; //【55域】 // 基本域: // 9F26 8b 应用密文AC // 9F27 1b 密文信息数据 // 9F10 max.32b 发卡行应用数据IAD // 9F37 4b 不可预知数 // 9F36 2b 应用交易计数器ATC // 95 5b 终端验证结果TVR // 9A 3cn 交易日期(6位有效数字,YYMMDD) // 9C 1cn 交易类型(2位有效数字) // 9F02 6cn 授权金额(12位有效数字) // 5F2A 2cn 交易货币代码(3位有效数字) // 82 2b 应用交互特征AIP // 9F1A 2cn 终端国家代码(3位有效数字) // 9F03 6cn 其他金额(12位有效数字) // 9F33 3b 终端性能 "E0C900" // 可选域: //添加9F26,9F27,9F10,9F33的数据 char *pCID = new char[4]; ZeroMemory(pCID, 4); HexBuf2StrBuf(&bt9f27, &pCID, 1); char *pIssueBankLen = new char[4]; ZeroMemory(pIssueBankLen, 4); int len9f10 = tmpResult.length() - 26 - 4; int lenHigh, lenLow; len9f10 = len9f10 / 2; lenHigh = len9f10 / 16; lenLow = len9f10 % 16; BYTE bt9f10; bt9f10 = (lenHigh << 4) + lenLow; HexBuf2StrBuf(&bt9f10, &pIssueBankLen, 1); baseICData += "9F2608" + tmpResult.substr(10, 16) + "9F2701" + pCID + "9F10" + pIssueBankLen + tmpResult.substr(26, tmpResult.length() - 26 - 4) + "9F3303" + "E0C900"; result = "ACTION," + actionType + "|" + "ATCCODE," + tmpResult.substr(6, 4) + "|" + "ARQCCODE," + tmpResult.substr(10, 16) + "|" + "MAC," + tmpResult.substr(26, tmpResult.length() - 26 - 4) + "|" + "ARQCSIZE," + string(arqcLen) + "|" + "ARQCDATA," + m_pDataToARQC + "|EXPIREDATE," + pExpireDate + "|T2ACCOUNT," + t2ICAccount + "|T2CARDSERIAL," + t2ICCardSerial + "|T2CVC," + t2ICCVC + "|T2TRACK2," + t2ICTrack2 + "|CARDCAT," + cardType + "|ICTAGS," + baseICData; ctx->Ans.result = result.c_str(); string txtresult = ""; txtresult = "ACTION," + actionType + "|" + "ATCCODE," + tmpResult.substr(6, 4) + "|" + "ARQCCODE," + tmpResult.substr(10, 16) + "|" + "MAC," + tmpResult.substr(26, tmpResult.length() - 26 - 4) + "|" + "ARQCSIZE," + string(arqcLen) + "|" + "ARQCDATA," + m_pDataToARQC + "|T2ACCOUNT(F6)," + t2ICAccount.substr(0, 6) + "|T2ACCOUNT(L4)," + t2ICAccount.substr(t2ICAccount.length() - 4, 4) + "|T2CARDSERIAL(len)," + t2ICCardSerial + "|CARDCAT," + cardType; Dbg("data to host(less)[%s],baseICData length:%d", txtresult.c_str(), baseICData.length()); if (m_pDataToARQC != NULL) { delete []m_pDataToARQC; m_pDataToARQC = NULL; } ctx->Answer(Error_Succeed); return 0; } int CContactlessCardFSM::PostOnline(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); Dbg("post online data[%s]",(LPCTSTR)ctx->Req.data); m_pCardProcess->SplitOnlineReplyData(ctx->Req.data,strlen(ctx->Req.data)); int issBnkAuth = m_pCardProcess->IssueBankAuth(CARD_MACHINE_RFIC,m_pRFIC); CSimpleStringA csTransEnd; if (issBnkAuth == 0) { int transEnd = m_pCardProcess->TransEnd(CARD_MACHINE_RFIC,m_pRFIC,m_bCDA); if (transEnd == 0) csTransEnd = "TRANSEND,0"; else if (transEnd == 1) csTransEnd = "TRANSEND,1"; } else csTransEnd = "TRANSEND,1"; ctx->Ans.result = csTransEnd; //PBYTE pData = new BYTE[MAX_IC_BUFFER_SIZE]; //ZeroMemory(pData,MAX_IC_BUFFER_SIZE); //int size = StrBuf2HexBuf(ctx->Req.data,&pData); //if (size > 0) //m_pCardProcess->ExecuteIssuerScript(CARD_MACHINE_ISSUER,m_pRFIC); //else //{ // Dbg("Wrong post on line data[%s]",ctx->Req.data); // ctx->Answer(Error_Unexpect); //} ctx->Answer(Error_Succeed); return 0; } int CContactlessCardFSM::EjectCard(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); ErrorCodeEnum eErr; //eErr = MachineMoveCardFrontGate(); m_pCardProcess->DataInit(); int ret = 0; DWORD dwStart = GetTickCount(); DWORD dwEnd = dwStart; while(1) { if (m_bExit) { ret = 2; break; } dwEnd = GetTickCount(); if ((dwEnd-dwStart) > 58*1000) { ret = 2; break; } ErrorCodeEnum eErr = m_pRFIC->GetDevStatus(devStatus); if (eErr == Error_Succeed) { Dbg("devStatus.eMedia %d",devStatus.eMediaPos); if (devStatus.eMediaPos == CI_MEDIA_RF || devStatus.eMediaPos == CI_MEDIA_NOTPRESENT) { if (devStatus.eMediaPos == CI_MEDIA_NOTPRESENT) ret = 0; else if (devStatus.eMediaPos == CI_MEDIA_RF) ret = 1; break; } } Sleep(100); } Dbg("oiltest eject"); if (ctx != NULL) ctx->Answer(Error_Succeed); return ret; } int CContactlessCardFSM::WaitFetchingCard() { LOG_FUNCTION(); int waitTries = 0; LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_ON,"ContactCard(fetch) warning on"); do { if (GetDevStatus()){ if (devStatus.eMediaPos == CI_MEDIA_RF){ Sleep(WAIT_INTERVAL); waitTries++; } else if (devStatus.eMediaPos == CI_MEDIA_NOTPRESENT){ waitTries = 0; LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_OFF,"ContactCard(fetch) warning off"); return 0; } }else { LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_OFF,"ContactCard(fetch) warning off"); return 1; } }while (waitTries < WAIT_TRY_NUM); LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_OFF,"ContactCard(fetch) warning off"); return 2; } int CContactlessCardFSM::QueryCardInfo(SpReqAnsContext::Pointer ctx) { RFICReaderStatus devStatus; ErrorCodeEnum eErr = m_pRFIC->GetDevStatus(devStatus); if (eErr != Error_Succeed) { Dbg("GetDevStatus failed(%d).",eErr); ctx->Answer(Error_Unexpect); return 1; } int ret = 0; Dbg("media pos:%d",devStatus.eMediaPos); switch(devStatus.eMediaPos) { case CI_MEDIA_IC: ret = 2; break; case CI_MEDIA_NOT_IC: ret = 3; break; case CI_MEDIA_RF: ret = 4; break; case CI_MEDIA_NOTPRESENT: default: ret = 0; break; } ctx->Ans.position = ret; ctx->Answer(Error_Succeed); return ret; } void CContactlessCardFSM::LogErrInfo(const char* msgHead) { DevErrorInfo errInfo; ErrorCodeEnum eErr = m_pRFIC->GetLastErr(errInfo); if (eErr == Error_Succeed) Dbg("%s,%s",msgHead,errInfo.szErrMsg); }