#ifndef __PINPAD_FSM_H #define __PINPAD_FSM_H #pragma once #include "SpFSM.h" #include "toolkit.h" #include "SpUtility.h" #include "DevFSMCommBase.hpp" #include "CommEntityUtil.hpp" #include "PinPad_UserErrorCode.h" #include "json/json.h" enum EvtType { USER_EVT_TEST = EVT_USER+1, USER_EVT_ANY_INPUT_TIMER, USER_EVT_QUIT, USER_EVT_INIT, USER_EVT_INITFINISHED, USER_EVT_SETACCOUNT, USER_EVT_SETACCOUNTFINISHED, USER_EVT_INPUTCANCEL, USER_EVT_INPUTWAITINGMORE, USER_EVT_EXIT, USER_EVT_GETINPUT_SM, USER_EVT_GETINPUT_SM_FINISHED, USER_EVT_LOADKEY_SM, USER_EVT_LOADKEY_SM_FINISHED, USER_EVT_ENCRYPT_SM, USER_EVT_ENCRYPT_SM_FINISHED, USER_EVT_GET_CHECKCODE, USER_EVT_GET_CHECKCODE_FINISHED, USER_EVT_TODO_INIT, USER_EVT_TODO_INIT_FINISHED, USER_EVT_GETINPUT_JS, USER_EVT_GETINPUT_JS_FINISHED, }; #include "PinPad_server_g.h" #include "PinPad_msg_g.h" #include "PinPadClass.h" using namespace PinPad; #include using namespace std; class CPinPadEntity; class CPinPadFSM; unsigned int __stdcall DoWork(void* pData); class PinPadInitFinishedEvent : public FSMEvent { public: PinPadInitFinishedEvent() : FSMEvent(USER_EVT_INITFINISHED){} ~PinPadInitFinishedEvent(){} }; class InputCancelEvent : public FSMEvent { public: InputCancelEvent() : FSMEvent(USER_EVT_INPUTCANCEL){} ~InputCancelEvent(){} }; class InputWaitingMoreEvent : public FSMEvent { public: InputWaitingMoreEvent() : FSMEvent(USER_EVT_INPUTWAITINGMORE){} ~InputWaitingMoreEvent(){} }; class GetInputSMEvent : public FSMEvent { public: GetInputSMEvent() : FSMEvent(USER_EVT_GETINPUT_SM){} ~GetInputSMEvent(){} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("GetInputSMEvent")("InvalidState"); ctx->Answer(Error_InvalidState); } } }; class GetInputJSEvent : public FSMEvent { public: GetInputJSEvent() : FSMEvent(USER_EVT_GETINPUT_JS) {} ~GetInputJSEvent() {} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("InvalidState"); } }; class LoadKeySMEvent : public FSMEvent { public: LoadKeySMEvent() : FSMEvent(USER_EVT_LOADKEY_SM){} ~LoadKeySMEvent(){} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("LoadKeySMEvent")("InvalidState"); ctx->Answer(Error_InvalidState); } } }; class EncryptSMEvent : public FSMEvent { public: EncryptSMEvent() : FSMEvent(USER_EVT_ENCRYPT_SM){} ~EncryptSMEvent(){} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("EncryptSMEvent")("InvalidState"); ctx->Answer(Error_InvalidState); } } }; class GetCheckCodeEvent : public FSMEvent { public: GetCheckCodeEvent() : FSMEvent(USER_EVT_GET_CHECKCODE){} ~GetCheckCodeEvent(){} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("GetCheckCodeEvent")("InvalidState"); ctx->Answer(Error_InvalidState); } } }; class CPinPadFSM : public CCommDevFSM { public: enum {s0,s1,s2,s3,s4,s5,s6}; BEGIN_FSM_STATE(CPinPadFSM) 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, "Input", s3_on_entry, s3_on_exit, s3_on_event) FSM_STATE_ENTRY(s4, "AccessAuth", s4_on_entry, s4_on_exit, s4_on_event) FSM_STATE_ENTRY(s5, "Failed", s5_on_entry, s5_on_exit, s5_on_event) FSM_STATE_ENTRY(s6, "InitFailed", s6_on_entry, s6_on_exit, s6_on_event) END_FSM_STATE() BEGIN_FSM_RULE(CPinPadFSM, s0) FSM_RULE_ENTRY(s0, s1, USER_EVT_INIT, 0) FSM_RULE_ENTRY(s1, s2, USER_EVT_INITFINISHED, 0) FSM_RULE_ENTRY(s1, s6, USER_EVT_INITFINISHED, 1) FSM_RULE_ENTRY(s2, s3, USER_EVT_GETINPUT_SM, 0) FSM_RULE_ENTRY(s2, s3, USER_EVT_GETINPUT_JS, 0) FSM_RULE_ENTRY(s2, s4, USER_EVT_LOADKEY_SM, 2) FSM_RULE_ENTRY(s2, s4, USER_EVT_ENCRYPT_SM, 2) FSM_RULE_ENTRY(s2, s0, USER_EVT_TODO_INIT_FINISHED, 0) FSM_RULE_ENTRY(s3, s2, USER_EVT_GETINPUT_SM_FINISHED, 0) FSM_RULE_ENTRY(s3, s2, USER_EVT_GETINPUT_JS_FINISHED, 0) FSM_RULE_ENTRY(s3, s2, USER_EVT_EXIT, 0) FSM_RULE_ENTRY(s4, s2, USER_EVT_LOADKEY_SM_FINISHED, 0) FSM_RULE_ENTRY(s4, s2, USER_EVT_ENCRYPT_SM_FINISHED, 0) FSM_RULE_ENTRY(s5, s0, USER_EVT_TODO_INIT_FINISHED, 0) FSM_RULE_ENTRY(s6, s0, USER_EVT_TODO_INIT_FINISHED, 0) END_FSM_RULE() CPinPadFSM() : m_bFrontCancel(false), m_bWaitingMore(false), m_bExit(false), m_bPlainPin(true), m_bStartPinInputOK(false), m_bEntityExit(false), m_bPinInput(false), m_bLoadKey(false), m_bEncrypt(false) , m_dwDevCommFailCount(0), m_dwPinPadRunCount(0), m_encryptkey(1) , m_bSM(false), m_bSMLoaded(false), m_szModel(""), m_szType("") , m_szVendor(""), m_bPinInputJS(false), m_bUseBackupSN(true), m_bSetParamOnce(false){ HARDWARE_ENTITY_RESET_ENTITYID(m_entCode, 0x206); ZeroMemory(&m_adapterInfo, sizeof(m_adapterInfo)); } ~CPinPadFSM(){ m_bEntityExit = true; } virtual ErrorCodeEnum OnInit(); virtual ErrorCodeEnum OnExit(); //void DoWork(); 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); int Initial(); void push_char(char *buf, int *len, int c); void pop_char(char *buf, int *len,bool bClear=true); void clear_char(char *buf, int *len); bool Get12Account(char *szAcc); int GetInput(SpReqAnsContext::Pointer ctxSM); ErrorCodeEnum GetEncryptText(SpReqAnsContext::Pointer ctxSM); void SetExitFlag(){m_bExit = true;} bool GetEntityExit() { return m_bEntityExit;} void SetCtx(SpReqAnsContext::Pointer ctxSM) { m_inputSMCtx = ctxSM; m_bPinInput = true; m_bPinInputJS = false; } bool GetCtx(SpReqAnsContext::Pointer& ctxSM) { if (m_inputSMCtx == NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("ctxSM is null"); return false; } ctxSM = m_inputSMCtx; return true; } void SetJSCtx(SpReqAnsContext::Pointer ctxJS) { m_inputJSCtx = ctxJS; m_bPinInputJS = true; m_bPinInput = false; } bool GetJSCtx(SpReqAnsContext::Pointer& ctxJS) { if (m_inputJSCtx == NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("ctxJS is null"); return false; } ctxJS = m_inputJSCtx; return true; } int GetInputJS(SpReqAnsContext::Pointer ctxJS); ErrorCodeEnum GetEncryptTextJS(SpReqAnsContext::Pointer ctxJS); ErrorCodeEnum GetDevInfo(DevCategoryInfo &devInfo); int LoadKeySM(SpReqAnsContext::Pointer ctx); int EncryptSM(SpReqAnsContext::Pointer ctx); ErrorCodeEnum GetCheckCode(SpReqAnsContext::Pointer ctx); int GetEncryptKey(int &devFunc,int &loadFunc) { devFunc = loadFunc = 0; devFunc = m_encryptkey; int tmp = 0; if (m_bSMLoaded) tmp += 2; if (m_bSMLoaded) loadFunc = 2; else loadFunc = tmp; return 0; } void SelfTest(EntityTestEnum eTestType,CSmartPointer pTransactionContext); bool IsInGetInputJS() { return m_bPinInputJS; } public: SP::Toolkit::CConditionVarPlus m_hInputConVar; SP::Toolkit::CConditionVarPlus m_hInitConVar; private: SpReqAnsContext::Pointer m_inputSMCtx; SpReqAnsContext::Pointer m_inputJSCtx; char m_szAccount[MAX_ACCOUNT_LEN]; bool m_bFrontCancel,m_bWaitingMore,m_bExit,m_bPlainPin,m_bEntityExit, m_bStartPinInputOK ,m_bPinInput,m_bLoadKey,m_bEncrypt,m_bSM,m_bSMLoaded, m_bPinInputJS, m_bUseBackupSN/*if use backup sn*/, m_bSetParamOnce/*call SetParam Only once*/; ULLINT m_ullBeginTime, m_ullEndTime, m_ullAdpFileLoadCost, m_ullEntityStart; CSimpleStringA m_deviceNo, m_devCheckData,m_keySNSM,m_szModel,m_szType,m_szVendor; char m_buf[4]; DWORD m_dwDevCommFailCount,m_dwPinPadRunCount; int m_encryptkey; CSimpleStringA m_lastCheckCode; }; struct InitTask : public ITaskSp { CPinPadFSM *fsm; InitTask(CPinPadFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_INITFINISHED); e->param1 = fsm->Initial(); fsm->PostEventFIFO(e); } }; struct LoadKeySMTask : public ITaskSp { CPinPadFSM* fsm; SpReqAnsContext::Pointer ctx; LoadKeySMTask(CPinPadFSM* f) : fsm(f) {} void Process() { LOG_FUNCTION(); FSMEvent *e = new FSMEvent(USER_EVT_LOADKEY_SM_FINISHED); e->param1 = fsm->LoadKeySM(ctx); fsm->PostEventFIFO(e); } }; struct EncryptSMTask : public ITaskSp { CPinPadFSM* fsm; SpReqAnsContext::Pointer ctx; EncryptSMTask(CPinPadFSM* f) : fsm(f) {} void Process() { LOG_FUNCTION(); FSMEvent *e = new FSMEvent(USER_EVT_ENCRYPT_SM_FINISHED); e->param1 = fsm->EncryptSM(ctx); fsm->PostEventFIFO(e); } }; struct GetCheckCodeTask : public ITaskSp { CPinPadFSM* fsm; SpReqAnsContext::Pointer ctx; GetCheckCodeTask(CPinPadFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_GET_CHECKCODE_FINISHED); e->param1 = fsm->GetCheckCode(ctx); fsm->PostEventFIFO(e); } }; template class TimerOutHelper : public ITimerListener { public: typedef void (T::*FuncTimer)(void *pUserdata); TimerOutHelper(T *p, FuncTimer pTimerFunc, void *pUserData, bool bDeleteSelf = false) : m_pObject(p), m_pUserData(pUserData), m_pTimer(pTimerFunc), m_bDeleteSelf(bDeleteSelf) {} virtual void OnTimeout(DWORD dwTimerID) { (m_pObject->*m_pTimer)(m_pUserData); if (m_bDeleteSelf) delete this; } private: void *m_pUserData; T *m_pObject; FuncTimer m_pTimer; bool m_bDeleteSelf; }; #endif //__PINPAD_FSM_H