#ifndef _CONTACTLESS_FSM_H #define _CONTACTLESS_FSM_H #pragma once #include "SpFSM.h" #include "CommEntityUtil.hpp" #include "DevFSMCommBase.hpp" #include "RFICClass.h" #include "CardAssist.h" #include "ICDataElement.h" #include "ContactlessCard_server_g.h" #include "ContactlessCard_msg_g.h" enum EvtType { USER_EVT_TEST = EVT_USER + 1, USER_EVT_QUIT, USER_EVT_INIT, USER_EVT_INITFINISHED, USER_EVT_ACCEPT, USER_EVT_ACCEPT_CANCEL, USER_EVT_ACCEPTFINISHED, USER_EVT_EJECT, USER_EVT_EJECTFINISHED, USER_EVT_WAITFINISHED, USER_EVT_CAPTUREFINISHED, USER_EVT_WAITFETCHINGTIMEOUT, USER_EVT_PREONLINE, USER_EVT_POSTONLINE, USER_EVT_PREONLINEFINISHED, USER_EVT_POSTONLINEFINISHED, USER_EVT_RESET, USER_EVT_RESETFINISHED, USER_EVT_EXIT, USER_EVT_READ, USER_EVT_READ_FINISHED, USER_EVT_QUERY_CARD_INFO, USER_EVT_QUERY_CARD_INFO_FINISHED, }; using namespace ContactlessCard; using lpCMBdecodeMag2 = int(*)(char* mag2Data, char* data); using lpCMBdecodeEx = int(*)(char* magData, char* type, char* data); class CContactlessCardEntity; class CContactlessCardFSM; struct Track2Data { int status; CSimpleStringA t2Account; CSimpleStringA t2Region; CSimpleStringA t2CardSerial; CSimpleStringA t2CVC; CSimpleStringA t2ExpireDate; }; struct CMBBin { CSimpleStringA bin;//6 byte long bool bIC;//IC:true or mag:false bool bDC;//debit:true,credit:false }; class CardAcceptEvent : public FSMEvent { public: CardAcceptEvent() : FSMEvent(USER_EVT_ACCEPT) {} ~CardAcceptEvent() {} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) { Dbg("card accept unhandled"); ctx->Answer(Error_InvalidState); } } }; class PreOnlineEvent : public FSMEvent { public: PreOnlineEvent() : FSMEvent(USER_EVT_PREONLINE) {} ~PreOnlineEvent() {} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) ctx->Answer(Error_InvalidState); } protected: private: }; class PostOnlineEvent : public FSMEvent { public: PostOnlineEvent() : FSMEvent(USER_EVT_POSTONLINE) {} ~PostOnlineEvent() {} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) ctx->Answer(Error_InvalidState); } protected: private: }; class CardEjectEvent : public FSMEvent { public: CardEjectEvent() : FSMEvent(USER_EVT_EJECT) {} ~CardEjectEvent() {} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) ctx->Answer(Error_InvalidState); } protected: private: }; class ResetDeviceEvent : public FSMEvent { public: ResetDeviceEvent() : FSMEvent(USER_EVT_RESET) {} ~ResetDeviceEvent() {} protected: private: }; class ResetFinishedEvent : public FSMEvent { public: ResetFinishedEvent() : FSMEvent(USER_EVT_RESETFINISHED) {} ~ResetFinishedEvent() {} protected: private: }; class QueryCardInfoEvent : public FSMEvent { public: QueryCardInfoEvent() : FSMEvent(USER_EVT_QUERY_CARD_INFO) {} ~QueryCardInfoEvent() {} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) ctx->Answer(Error_InvalidState); } protected: private: }; class CContactlessCardFSM : public CCommDevFSM { public: enum { s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 }; BEGIN_FSM_STATE(CContactlessCardFSM) FSM_STATE_ENTRY(s0, "Init", s0_on_entry, s0_on_exit, s0_on_event) FSM_STATE_ENTRY(s1, "Initializing", s1_on_entry, s1_on_exit, s1_on_event) FSM_STATE_ENTRY(s2, "Idle", s2_on_entry, s2_on_exit, s2_on_event) FSM_STATE_ENTRY(s3, "Accepting", s3_on_entry, s3_on_exit, s3_on_event) FSM_STATE_ENTRY(s4, "Hold", s4_on_entry, s4_on_exit, s4_on_event) FSM_STATE_ENTRY(s5, "Reading", s5_on_entry, s5_on_exit, s5_on_event) FSM_STATE_ENTRY(s6, "Ejecting", s6_on_entry, s6_on_exit, s6_on_event) FSM_STATE_ENTRY(s7, "WaitFetching", s7_on_entry, s7_on_exit, s7_on_event) FSM_STATE_ENTRY(s8, "Capturing", s8_on_entry, s8_on_exit, s8_on_event) FSM_STATE_ENTRY(s9, "Failed", s9_on_entry, s9_on_exit, s9_on_event) END_FSM_STATE() BEGIN_FSM_RULE(CContactlessCardFSM, s0) FSM_RULE_ENTRY(s0, s1, USER_EVT_INIT, 0) FSM_RULE_ENTRY(s0, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s1, s2, USER_EVT_INITFINISHED, 0) FSM_RULE_ENTRY(s1, s9, USER_EVT_INITFINISHED, 1) FSM_RULE_ENTRY(s1, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s2, s3, USER_EVT_ACCEPT, 0) FSM_RULE_ENTRY(s2, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s2, s6, USER_EVT_EJECT, 0) FSM_RULE_ENTRY(s3, s4, USER_EVT_ACCEPTFINISHED, 0) FSM_RULE_ENTRY(s3, s9, USER_EVT_ACCEPTFINISHED, 1) FSM_RULE_ENTRY(s3, s2, USER_EVT_ACCEPTFINISHED, 2) FSM_RULE_ENTRY(s3, s2, USER_EVT_ACCEPTFINISHED, 3) FSM_RULE_ENTRY(s3, s7, USER_EVT_ACCEPTFINISHED, 4) FSM_RULE_ENTRY(s3, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s4, s6, USER_EVT_EJECT, 0) FSM_RULE_ENTRY(s4, s6, USER_EVT_EXIT, 0) FSM_RULE_ENTRY(s4, s2, USER_EVT_QUERY_CARD_INFO_FINISHED, 0) FSM_RULE_ENTRY(s4, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s5, s4, USER_EVT_READ_FINISHED, 0) FSM_RULE_ENTRY(s5, s9, USER_EVT_READ_FINISHED, 1) FSM_RULE_ENTRY(s5, s2, USER_EVT_READ_FINISHED, 2) FSM_RULE_ENTRY(s5, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s5, s6, USER_EVT_EXIT, 0) FSM_RULE_ENTRY(s6, s7, USER_EVT_EJECTFINISHED, 1) FSM_RULE_ENTRY(s6, s7, USER_EVT_EJECTFINISHED, 0) FSM_RULE_ENTRY(s6, s7, USER_EVT_EJECTFINISHED, 2) FSM_RULE_ENTRY(s6, s2, USER_EVT_EXIT, 0) FSM_RULE_ENTRY(s6, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s7, s2, USER_EVT_WAITFINISHED, 0) FSM_RULE_ENTRY(s7, s2, USER_EVT_WAITFINISHED, 2) FSM_RULE_ENTRY(s7, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s8, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s9, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s9, s2, USER_EVT_RESETFINISHED, 0) FSM_RULE_ENTRY(s9, s2, USER_EVT_RESETFINISHED, 1) END_FSM_RULE() CContactlessCardFSM() : m_pRFIC(NULL), m_bCancelAccept(false), m_bWaitingAccept(false), m_bWaitAccepteMore(false), m_bExit(false), m_resetTimes(0), m_testResult(Error_Succeed) //,m_pTACReject(NULL),m_pIACOnline(NULL),m_pTACOnline(NULL),m_pIACDefault(NULL),m_pTACDefault(NULL) , m_bCDA(false), m_pDataToARQC(NULL), m_bSM(false), m_bOnlineOnly(false) { m_aidList.Init(3); m_aidList[0] = "A000000333"; m_aidList[1] = "A0000000108888"; m_aidList[2] = "A000000790"; } ~CContactlessCardFSM() {} virtual ErrorCodeEnum OnInit(); virtual ErrorCodeEnum OnExit(); void s0_on_entry(); void s0_on_exit(); unsigned int s0_on_event(FSMEvent* event); void s1_on_entry(); void s1_on_exit(); unsigned int s1_on_event(FSMEvent* event); void s2_on_entry(); void s2_on_exit(); unsigned int s2_on_event(FSMEvent* event); void s3_on_entry(); void s3_on_exit(); unsigned int s3_on_event(FSMEvent* event); void s4_on_entry(); void s4_on_exit(); unsigned int s4_on_event(FSMEvent* event); void s5_on_entry(); void s5_on_exit(); unsigned int s5_on_event(FSMEvent* event); void s6_on_entry(); void s6_on_exit(); unsigned int s6_on_event(FSMEvent* event); void s7_on_entry(); void s7_on_exit(); unsigned int s7_on_event(FSMEvent* event); void s8_on_entry(); void s8_on_exit(); unsigned int s8_on_event(FSMEvent* event); void s9_on_entry(); void s9_on_exit(); unsigned int s9_on_event(FSMEvent* event); int Initial(); ErrorCodeEnum Load(); bool GetDevStatus(); int InternalAcceptCard(); int AcceptCard(SpReqAnsContext::Pointer ctx); //int ReadCard(SpReqAnsContext::Pointer ctx); int PreOnline(SpReqAnsContext::Pointer ctx); int PostOnline(SpReqAnsContext::Pointer ctx); int EjectCard(SpReqAnsContext::Pointer ctx); int Reset(); int WaitFetchingCard(); int QueryCardInfo(SpReqAnsContext::Pointer ctx); bool GetWaitFlag() { return m_bWaitingAccept; } void SetWaitMore() { m_bWaitAccepteMore = true; } void SetExitFlag(bool bFlag = true) { m_bExit = bFlag; } void SelfTest(EntityTestEnum eTestType, CSmartPointer pTransactionContext) { pTransactionContext->SendAnswer(m_testResult); } DevStateEnum GetDevState() { return m_eDevState; } protected: int m_iInsertTries; int m_resetTries; int m_ejectTries; private: int m_resetTimes; lpCMBdecodeMag2 cmdDecodeMag2; lpCMBdecodeEx cmdDecodeEx; bool m_devInit, m_bCancelAccept, m_bWaitingAccept, m_bWaitAccepteMore, m_bExit, m_bIssued, m_bSM; ErrorCodeEnum m_testResult; int m_CardInit, m_CardRemains, m_CardIssued, m_CardCaptured, m_CardMixed, m_CardPercent; RFICReaderStatus devStatus; RFICClass* m_pRFIC; DevStateEnum m_eDevState; CCardProcess* m_pCardProcess; char* m_pDataToARQC; long xxTest; CAutoArray m_aidList; char m_AuthCode[2]; bool m_bOnlineOnly, m_bCDA; int SplitTrack2(CSimpleStringA pTrack2, Track2Data& decodeData); void LogErrInfo(const char*); }; struct InitTask : public ITaskSp { CContactlessCardFSM* fsm; InitTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent* e = new FSMEvent(USER_EVT_INITFINISHED); e->param1 = fsm->Initial(); fsm->PostEventFIFO(e); } }; struct AcceptTask : public ITaskSp { CContactlessCardFSM* fsm; SpReqAnsContext::Pointer ctx; AcceptTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { LOG_FUNCTION(); FSMEvent* e = new FSMEvent(USER_EVT_ACCEPTFINISHED); e->param1 = fsm->AcceptCard(ctx); fsm->PostEventFIFO(e); } }; struct PreOnlineTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; PreOnlineTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent* e = new FSMEvent(USER_EVT_PREONLINEFINISHED); e->param1 = fsm->PreOnline(ctx); fsm->PostEventFIFO(e); } }; struct PostOnlineTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; PostOnlineTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent* e = new FSMEvent(USER_EVT_POSTONLINEFINISHED); e->param1 = fsm->PostOnline(ctx); fsm->PostEventFIFO(e); } }; struct EjectTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; EjectTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent* e = new FSMEvent(USER_EVT_EJECTFINISHED); e->param1 = fsm->EjectCard(ctx); fsm->PostEventFIFO(e); } }; struct WaitFetchingTask : public ITaskSp { CContactlessCardFSM* fsm; WaitFetchingTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent* e = new FSMEvent(USER_EVT_WAITFINISHED); e->param1 = fsm->WaitFetchingCard(); fsm->PostEventFIFO(e); } }; struct ResetTask : public ITaskSp { CContactlessCardFSM* fsm; ResetTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { ResetFinishedEvent* e = new ResetFinishedEvent(); e->param1 = fsm->Reset(); fsm->PostEventFIFO(e); } }; struct QueryCardInfoTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; QueryCardInfoTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent* e = new FSMEvent(USER_EVT_QUERY_CARD_INFO_FINISHED); e->param1 = fsm->QueryCardInfo(ctx); fsm->PostEventFIFO(e); } }; #endif //_CONTACTLESS_FSM_H