#ifndef _COMM_DEVICE_FSM_BASE_HPP_ #define _COMM_DEVICE_FSM_BASE_HPP_ #include "DevEntityCommBase.hpp" #include "CommEntityUtil.hpp" #include "SpFSM.h" #include "RVCComm.h" #include "DevErrorCode.h" #include "DeviceBaseClass.h" #include "publicFunExport.h" #include #include #include #include #include "fileutil.h" #include "RVCEventCode.h" #if defined(_MSC_VER) #pragma comment(lib, "Version.lib") #endif //_MSC_VER using DevAdaptObjCreateFunc = ErrorCodeEnum(*)(DeviceBaseClass*& pOutDevAptObj); using DevAdaptObjReleaseFunc = ErrorCodeEnum(*)(DeviceBaseClass*& pInDevAptObj); using GetPrefixErrMsgFunc = void(*)(char* szErrMsg, DWORD* pMsgLen); typedef ErrorCodeEnum(*GetDevAdapterVersionFunc)(DevSoftVersion& retVersion); #define HARDWARE_ENTITY_RESET_ENTITYID(ent, entityID) \ do{\ memset(&ent, 0, sizeof(ent)); \ ent.dwEntityId = entityID; \ } while (false) #define HARDWARE_ENTITY_MAKE_ERRORCODE_TO_BUSINESS(ec) \ MAKE_SLV_ERRORCODE_TO_BUSINESS(ec.dwEntityId, ec.dwVendorErroCode, ec.dwReserved) enum PageType { PageType_Init, PageType_MainPage, PageType_UserDesktop, PageType_Other, }; template struct DevAdptLibHelper { private: bool CheckAndGetMapAdatperName(const CSimpleStringA& strPath, CSimpleStringA& replaceAdapterName) { bool result = false; CSimpleStringA strTest = m_strAdapterName.IsNullOrEmpty() ? strPath.GetData() : m_strAdapterName.GetData(); for (int i = 0; i < strTest.GetLength(); ++i) { if (strTest[i] >= 'A' && strTest[i] <= 'Z') strTest[i] = strTest[i] + ('a' - 'A'); } if (strTest.IndexOf("pinpad") != -1) { replaceAdapterName = "PinPad.self.1.1.dll"; result = true; } else if (strTest.IndexOf("cardissuer") != -1) { replaceAdapterName = "CardIssuer.self.1.1.dll"; result = true; } else if (strTest.IndexOf("contactlesscard") != -1) { replaceAdapterName = "ContactlessCard.self.1.1.dll"; result = true; } else if (strTest.IndexOf("fingerprint") != -1) { replaceAdapterName = "FingerPrint.self.1.1.dll"; result = true; } else if (strTest.IndexOf("gpio") != -1) { replaceAdapterName = "GPIO.self.1.1.dll"; result = true; } else if (strTest.IndexOf("idcertificate") != -1) { replaceAdapterName = "IDCertificate.self.1.1.dll"; result = true; } else if (strTest.IndexOf("hspscanner") != -1) { replaceAdapterName = "HSPSCanner.self.1.1.dll"; result = true; } return result; } bool PreLoadLib(CSimpleStringA& strFullLibPath) { bool result(false); ///*TODO: Test (80374374@1/23/2024)*/ DWORD d1; DWORD d2; DWORD d3; DWORD d4; if (!ExistsFileA(strFullLibPath)) { return result; } #ifndef DEVOPS_ON_PRD GetDllVersionInfo(strFullLibPath, d1, d2, d3, d4); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("dll %s version: %d.%d.%d.%d", strFullLibPath.GetData(), d1, d2, d3, d4); //VC16.0 [1920,1929] VS2019 142 if (d4 >= 1920 && d4 <= 1929 && d3 == 142) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("detect it built with VS2019, skip latter procedure, version: %d.%d.%d.%d", d1, d2, d3, d4); return result; } #endif CSimpleStringA strTest = strFullLibPath.GetData(); CSimpleStringA strSelf(true); if (CheckAndGetMapAdatperName(strTest, strSelf)) { int index = -1; for (int i = 0; i < strTest.GetLength(); ++i) if (strTest[i] == '\\' || strTest[i] == '/') index = i; if (index != -1) { toolkit_setenv("INVOKE_VENDOR_ADAPTER_NAME", strFullLibPath.GetData()); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("env:%s", strFullLibPath.GetData()); CSimpleStringA strAdapterName = strTest.SubString(index + 1); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("adapter name:%s", strAdapterName.GetData()); strTest[index + 1] = '\0'; //!!!! strFullLibPath = strTest.SubString(0, index + 1); strFullLibPath += strSelf; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("new adapter path:%s", strFullLibPath.GetData()); result = true; } } return result; } public: void SetAdapterName(const CSimpleStringA& strEntityName) { m_strAdapterName = strEntityName; } ErrorCodeEnum LoadLibAddress(const CSimpleStringA& strFullLibPath) { ErrorCodeEnum erroCode = Error_Succeed; CSimpleStringA strTemp = strFullLibPath.GetData(); #if defined(_MSC_VER) m_VS2010BridgeMode = PreLoadLib(strTemp); #endif //_MSC_VER do { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to load lib: %s", strTemp.GetData()); if (!ExistsFileA(strTemp)) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("the lib file %s is not existed!", strTemp.GetData()); erroCode = Error_NotExist; break; } int res = toolkit_dlopen(strTemp, &m_lib); if (res != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setResultCode(DEVICE_FSM_LOADADDR_DLOPEN_FAILED)("toolkit_dlopen[%s] failed with error %s.", strTemp.GetData(), toolkit_dlerror(&m_lib)); erroCode = Error_DevLoadFileFailed; break; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to get CreateDevComponent pointer address..."); if ((res = toolkit_dlsym(&m_lib, "CreateDevComponent", (void**)&pFuncCreateAdapt)) != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setResultCode(DEVICE_FSM_LOADADDR_CREATEOJ_FAILED)("Get 'CreateDevComponent' Func address failed with error: %s", toolkit_dlerror(&m_lib)); erroCode = Error_DevLoadFileFailed; break; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to get ReleaseDevComponent pointer address..."); if ((res = toolkit_dlsym(&m_lib, "ReleaseDevComponent", (void**)&pFuncReleaseAdapt)) != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setResultCode(DEVICE_FSM_LOADADDR_RELOJ_FAILED)("Get 'ReleaseDevComponent' Func address failed with error: %s", toolkit_dlerror(&m_lib)); erroCode = Error_DevLoadFileFailed; break; } #if defined(RVC_OS_WIN) DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to get GetMoreErrorDetail pointer address..."); if ((res = toolkit_dlsym(&m_lib, "GetMoreErrorDetail", (void**)&pFuncGetPrefixErr)) != 0) {//该接口是后面加到桥接层适配器的,所以报错不作强制性阻碍 pFuncGetPrefixErr = nullptr; } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Get 'GetMoreErrorDetail' Func address succ"); } #endif //RVC_OS_WIN } while (false); if (IS_FAILURED(erroCode)) { TearDown(); } return erroCode; } ErrorCodeEnum CreateDevAdptObject() { if (m_AdptObjPtr != nullptr) { return Error_AlreadyExist; } if (pFuncCreateAdapt == nullptr || pFuncReleaseAdapt == nullptr) { return Error_NotInit; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to get Adapter object..."); ErrorCodeEnum erroCode = pFuncCreateAdapt((DeviceBaseClass*&)m_AdptObjPtr); if (IS_FAILURED(erroCode)) { if (pFuncGetPrefixErr != nullptr) { char szErrMsg[MAX_DEV_ERROR_MSG_LEN]; memset(szErrMsg, '\0', sizeof(szErrMsg)); DWORD dwLen = MAX_DEV_ERROR_MSG_LEN; pFuncGetPrefixErr(szErrMsg, &dwLen); DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setResultCode(DEVICE_FSM_CREATE_DEVOBJ_FAILED)("Create device adapter object failed! EC=%s, Msg:[%s]" , SpStrError(erroCode), szErrMsg); } else { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setResultCode(DEVICE_FSM_CREATE_DEVOBJ_FAILED)("Create device adapter object failed! EC=%s", SpStrError(erroCode)); } return erroCode; } LOG_ASSERT(m_AdptObjPtr != nullptr); return Error_Succeed; } /** Integrate function LoadLibAddress and CreateDevAdptObject, please use LoadUpAdapterLibrary replace with it*/ ErrorCodeEnum LoadUp(const CSimpleStringA& strFullLibPath) { ErrorCodeEnum erroCode = LoadLibAddress(strFullLibPath); if (IS_SUCCEED(erroCode)) { erroCode = CreateDevAdptObject(); if (!IS_SUCCEED(erroCode)) { TearDown(); } } return erroCode; } void TearDown() { if (m_AdptObjPtr != nullptr) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("To DevClose..."); ULONGLONG ullStart = SP::Module::Comm::RVCGetTickCount(); ErrorCodeEnum result = m_AdptObjPtr->DevClose(); ULONGLONG ullEnd = SP::Module::Comm::RVCGetTickCount(); if (IS_FAILURED(result)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode(DEVICE_FSM_DEVCLOSE_FAILED)/*.setAPI("DevAdapter::DevClose") 不纳入适配器消费,因为不好分配RTA,只做调研*/ .setCostTime(ullEnd - ullStart)("DevClose returned %s", SpStrError(result)); } if (nullptr != pFuncReleaseAdapt) { DeviceBaseClass* devBasePtr = static_cast(m_AdptObjPtr); if (devBasePtr != nullptr) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("To Release DevAdapter Object..."); pFuncReleaseAdapt(devBasePtr); m_AdptObjPtr = nullptr; } } } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to dlclose DevAdapter libs..."); toolkit_dlclose(&m_lib); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("dlclose DevAdapter libs succ"); pFuncReleaseAdapt = pFuncCreateAdapt = nullptr; pFuncGetPrefixErr = nullptr; } #if defined(RVC_OS_WIN) ErrorCodeEnum GetDllVersionInfo(LPCTSTR lpcszFilePath, DWORD& dwMajor, DWORD& dwMinor, DWORD& dwBuild, DWORD& dwRevision) { char* buf = NULL; dwMajor = dwMinor = dwBuild = dwRevision = (DWORD)(-1); DWORD dwHnd; DWORD dwVerInfoSize; if (0 >= (dwVerInfoSize = GetFileVersionInfoSizeA(lpcszFilePath, &dwHnd))) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("GetFileVersionInfoSizeA failed: %u", GetLastError()); return Error_Unexpect; } buf = new char[dwVerInfoSize]; if (NULL == buf) { return Error_Resource; } // get file version info if (!GetFileVersionInfo(lpcszFilePath, dwHnd, dwVerInfoSize, buf)) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("GetFileVersionInfo failed: %u", GetLastError()); delete[] buf; return Error_Unexpect; } // get FileVersion string from resource VS_FIXEDFILEINFO* ptrVersion; unsigned int versionLen = 0; if (!VerQueryValue(buf, "\\", (void**)&ptrVersion, &versionLen)) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("VS_FIXEDFILEINFO failed: %u", GetLastError()); delete[] buf; return Error_Unexpect; } dwMajor = (ptrVersion->dwFileVersionMS >> 16) & 0x0000FFFF; dwMinor = ptrVersion->dwFileVersionMS & 0x0000FFFF; dwBuild = (ptrVersion->dwFileVersionLS >> 16) & 0x0000FFFF; dwRevision = ptrVersion->dwFileVersionLS & 0x0000FFFF; delete[] buf; return Error_Succeed; } #else ErrorCodeEnum GetDllVersionInfo(LPCTSTR lpcszFilePath, DWORD& dwMajor, DWORD& dwMinor, DWORD& dwBuild, DWORD& dwRevision) { dwMajor = dwMinor = dwBuild = dwRevision = 0; return Error_NotSupport; } #endif //RVC_OS_WIN #if defined(_MSC_VER) operator bool() const { return (m_AdptObjPtr != nullptr); } #else /** Linux 下不加此会影响 编译 Gifur@2023329]*/ explicit operator bool() const { return (m_AdptObjPtr != nullptr); } #endif //_MSC_VER operator DeviceBaseClass* () { return m_AdptObjPtr; } TSubAdpt* GetDevPointer() { return m_AdptObjPtr; } TSubAdpt* operator->() { if (m_AdptObjPtr == nullptr) { throw std::runtime_error("the dev class pointer is nullptr!!"); } return m_AdptObjPtr; } bool operator !=(TSubAdpt* rhs) { return !(m_AdptObjPtr == rhs); } bool operator !=(const DevAdptLibHelper& rhs) { return !(m_AdptObjPtr == rhs.operator->()); } DevAdptLibHelper() : pFuncCreateAdapt(nullptr), pFuncReleaseAdapt(nullptr), pFuncGetPrefixErr(nullptr) , m_AdptObjPtr(nullptr), m_VS2010BridgeMode(false), m_strAdapterName(true) { memset(&m_lib, 0, sizeof(toolkit_lib_t)); } ~DevAdptLibHelper() { TearDown(); } #if defined(RVC_OS_LINUX) DevAdptLibHelper(const DevAdptLibHelper&) = delete; DevAdptLibHelper& operator=(const DevAdptLibHelper&) = delete; #endif //RVC_OS_LINUX private: toolkit_lib_t m_lib; DevAdaptObjCreateFunc pFuncCreateAdapt; DevAdaptObjReleaseFunc pFuncReleaseAdapt; GetDevAdapterVersionFunc pFuncGetDevAdapterVer; GetPrefixErrMsgFunc pFuncGetPrefixErr; TSubAdpt* m_AdptObjPtr; bool m_VS2010BridgeMode; CSimpleStringA m_strAdapterName; }; struct AdaptorInfo { public: CSimpleStringA strVendor; CSimpleStringA strVersion; CSimpleStringA strBatch; CSimpleStringA strPort; CSimpleStringA strBaudrate; CSimpleStringA strPortNum; CSimpleStringA strPureAdapterName; AdaptorInfo() :strVendor(true), strVersion(true), strBatch(true) , strPort(true), strBaudrate(true) , strPortNum(true) , strPureAdapterName(true) { } int GetVersionInt() const { int result = 0; if (!strVersion.IsNullOrEmpty()) { result = atoi(strVersion.GetData()); } return result; } int GetBatchInt() const { int result = 0; if (!strBatch.IsNullOrEmpty()) { result = atoi(strBatch.GetData()); } return result; } int GetPortInt() const { int result = 0; if (!strPort.IsNullOrEmpty()) { result = atoi(strPort.GetData()); } return result; } int GetBaudrateInt() const { int result = 0; if (!strBaudrate.IsNullOrEmpty()) { result = atoi(strBaudrate.GetData()); } return result; } int GetPortNumInt() const { int result = 0; if (!strPortNum.IsNullOrEmpty()) { result = atoi(strPortNum.GetData()); } return result; } }; struct AdapterInfo : public AdaptorInfo { CSimpleStringA adapterFilePath; CSimpleStringA adapterFileName; DevCategoryInfo devCatInfo; AdapterInfo() :adapterFilePath(true), adapterFileName(true) { ZeroMemory(devCatInfo.szModel, sizeof(devCatInfo.szModel)); ZeroMemory(devCatInfo.szType, sizeof(devCatInfo.szType)); ZeroMemory(devCatInfo.szVendor, sizeof(devCatInfo.szVendor)); } void FulfillCategoryInfo(const DevCategoryInfo& rhs) { devCatInfo.eState = rhs.eState; devCatInfo.version.wMajor = rhs.version.wMajor; devCatInfo.version.wMinor = rhs.version.wMinor; devCatInfo.version.wRevision = rhs.version.wRevision; devCatInfo.version.wBuild = rhs.version.wBuild; strcpy(devCatInfo.szType, rhs.szType); strcpy(devCatInfo.szModel, rhs.szModel); strcpy(devCatInfo.szVendor, rhs.szVendor); CSimpleStringA strCatVersion = CSimpleStringA::Format("%d.%d.%d.%d", devCatInfo.version.wMajor, devCatInfo.version.wMinor, devCatInfo.version.wRevision, devCatInfo.version.wBuild); if (strlen(devCatInfo.szType) >= MAX_DEV_TYPE_LEN) { devCatInfo.szType[MAX_DEV_TYPE_LEN - 1] = '\0'; } if (strlen(devCatInfo.szModel) >= MAX_DEV_MODEL_LEN) { devCatInfo.szModel[MAX_DEV_MODEL_LEN - 1] = '\0'; } if (strlen(devCatInfo.szVendor) >= MAX_DEV_VENDOR_LEN) { devCatInfo.szVendor[MAX_DEV_VENDOR_LEN - 1] = '\0'; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("GetDevCategory")("{\"szVendor\":\"%s\",\"szType\":\"%s\",\"szModel\":\"%s\",\"szVersion\":\"%s\"}", devCatInfo.szVendor, devCatInfo.szType, devCatInfo.szModel, strCatVersion.GetData()); //oilyang@20250220 as device adapter have been decoupled from us, no need to check anymore //CheckCategoryInfoFormat(); } /* void CheckCategoryInfoFormat() { const int DEV_CATINFO_SUM = 3; char* devInfo[DEV_CATINFO_SUM] = { "szModel", "szVendor", "szType" }; for (int devSn = 0; devSn < DEV_CATINFO_SUM; devSn++) { CSimpleStringA strCatInfo; if (devSn == 0) strCatInfo = devCatInfo.szModel; else if (devSn == 1) strCatInfo = devCatInfo.szVendor; else if (devSn == 2) strCatInfo = devCatInfo.szType; if (!strCatInfo.IsNullOrEmpty()) { auto arr = strCatInfo.Split('#'); if (arr.GetCount() > 0) { for (int sec = 0; sec < arr.GetCount(); sec++) { auto arr2 = arr[sec].Split('='); if (arr2.GetCount() != 2) { if (devSn != 1)//szVendor 没有要求符合"key=value#"的格式 DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CheckDevInfoFormat, Wrong section of %s:%s", devInfo[devSn], arr[sec].GetData()); continue; } if ((strnicmp((LPCTSTR)arr2[0], "MID", strlen("MID")) == 0 && arr2[1].Compare("1.0") != 0) || (strnicmp((LPCTSTR)arr2[0], "CODE", strlen("CODE")) == 0 && arr2[1].Compare("UCS2") != 0)) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CheckDevInfoFormat, Wrong format of %s:%s", arr2[0].GetData(), arr2[1].GetData()); else if (strnicmp((LPCTSTR)arr2[0], "PID", strlen("PID")) == 0 || strnicmp((LPCTSTR)arr2[0], "FWID", strlen("FWID")) == 0) { string strData = arr2[1].GetData(); regex pattern(".{8,16}"); smatch sm; if (!regex_match(strData, sm, pattern)) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CheckDevInfoFormat, Wrong format of %s:%s", arr2[0].GetData(), arr2[1].GetData()); } else if (strnicmp((LPCTSTR)arr2[0], "STYLE", strlen("STYLE")) == 0) { string strData = arr2[1].GetData(); regex pattern("CL|IG"); smatch sm; if (!regex_match(strData, sm, pattern)) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CheckDevInfoFormat, Wrong format of %s:%s", arr2[0].GetData(), arr2[1].GetData()); } else if (strnicmp((LPCTSTR)arr2[0], "RF", strlen("RF")) == 0) { string strData = arr2[1].GetData(); regex pattern("Y|N"); smatch sm; if (!regex_match(strData, sm, pattern)) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CheckDevInfoFormat, Wrong format of %s:%s", arr2[0].GetData(), arr2[1].GetData()); } else if (strnicmp((LPCTSTR)arr2[0], "FUNCTION", strlen("FUNCTION")) == 0) { string strData = arr2[1].GetData(); //regex pattern("^(I|T|F|Y|IT|TI|IF|FI|TF|FT|IY|TY|FY|ITF|IFT|FIT|FTI|FIT|FTI)$");//stupid,how to write the right... composite of 'I'/'T'/'F'/'Y' regex pattern("^[ITFY]{1,4}$"); smatch sm; if (!regex_match(strData, sm, pattern)) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CheckDevInfoFormat, Wrong format of %s:%s", arr2[0].GetData(), arr2[1].GetData()); } } } else DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CheckDevInfoFormat, can't split from %s:%s", devInfo[devSn], strCatInfo.GetData()); } else DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CheckDevInfoFormat, %s is empty.", devInfo[devSn]); } } */ }; struct ErrorPackageEx { ErrorCodeEnum errCode; DWORD apiUserCode; CSimpleStringA devApi; bool bInBusiness; int costTime; CSimpleStringA funPath; ErrorPackageEx() :errCode(Error_Succeed), apiUserCode(0), devApi(true), bInBusiness(false), costTime(0), funPath(true) {} }; struct DevEntityErrorCode { DWORD dwEntityId; DWORD dwVendorId; DWORD dwVendorErroCode; DWORD dwReserved; DevEntityErrorCode() :dwEntityId(0), dwVendorId(0), dwVendorErroCode(0), dwReserved(0) {} void ResetWithEntityID(WORD wEntityID) { dwEntityId = dwVendorId = dwVendorErroCode = dwReserved = 0; dwEntityId = wEntityID; } void SetDevCode(DWORD devErrorCode, DWORD dwReservedCode) { dwVendorErroCode = devErrorCode; dwReserved = dwReservedCode; } DWORD GetCompleteErrorCode() const { return MAKE_SLV_ERRORCODE(dwEntityId, dwVendorId, dwVendorErroCode); } }; template class CCommDevFSM : public FSMImpl { public: CCommDevFSM() : m_iInWhatPage(PageType_Init),m_bOpened(false), m_bOpening(true), m_eDevState(DEVICE_STATUS_NOT_READY), m_preUIState('X') { } ErrorCodeEnum GetAndSplitDevErrInfo( CSimpleStringA& csErrMsg, WORD& wdDevErrCode, LPCTSTR lpszFuncNameForDisplay = ""); DWORD SetErrorAndLog(ErrorCodeEnum errCode, DWORD userCode, CSimpleStringA devApi, CSimpleStringA funPath, bool bInBusiness = false, int costTime = 0, CSimpleStringA logCode = "", CSimpleStringA context = "") { //set error info m_errPkgEx.errCode = errCode; m_errPkgEx.apiUserCode = userCode; m_errPkgEx.devApi = devApi; m_errPkgEx.bInBusiness = bInBusiness; m_errPkgEx.costTime = costTime; m_errPkgEx.funPath = funPath; //get DevAdapter vendor errmsg and log info WORD wdErrCode = 0; CSimpleStringA csErrMsg(true); ErrorCodeEnum ec = GetAndSplitDevErrInfo(csErrMsg, wdErrCode, ""); if (ec == Error_Succeed && wdErrCode != 0) { //oilyang@20200525 if have been set ErrorCode of entity defined (not device),use it directly if ((m_errPkgEx.apiUserCode >> 20) == m_entCode.dwEntityId) UpdateDEC(m_errPkgEx.apiUserCode); else UpdateDEC(wdErrCode); } else if (m_errPkgEx.apiUserCode != 0) { UpdateDEC(m_errPkgEx.apiUserCode); } //oilyang@20200525 if have been set ErrorCode of entity defined (not device),use it directly const DWORD dwCode = GetAlarmDEC(); const CSimpleStringA alarmMsg = CSimpleStringA::Format("{\"Function\":\"%s\", \"DevApi\":\"%s\", \"ReturnCode\":\"%s\", \"Msg\":\"%s\", \"Context\":\"%s\"}" , funPath.GetData(), devApi.GetData(), SpStrError(m_errPkgEx.errCode), csErrMsg.GetData(), context.GetData()); std::map msgInfo; msgInfo["ReturnCode"] = SpStrError(errCode); msgInfo["ErrMsg"] = csErrMsg.GetData(); msgInfo["Context"] = context.GetData(); std::pair strResult; strResult = generateJsonStr(msgInfo); CSimpleStringA csErrMsgWithReturnCode = strResult.second.c_str(); CSimpleStringA tmpRTA(true), tmpDesc(true); this->GetEntityBase()->GetFunction()->GetVTMErrMsg(dwCode, tmpDesc, tmpRTA); if (bInBusiness) { LogError(Severity_High, m_errPkgEx.errCode, dwCode, alarmMsg.GetData()); DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_USER).setLogCode(logCode).setAPI(devApi).setResultCode(tmpRTA.GetData()).setCostTime(costTime)(csErrMsgWithReturnCode.GetData()); } else { LogWarn(Severity_High, m_errPkgEx.errCode, dwCode, alarmMsg.GetData()); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setLogCode(logCode).setAPI(devApi).setResultCode(tmpRTA.GetData()).setCostTime(costTime)(csErrMsgWithReturnCode.GetData()); } return dwCode; } //在旧dep路径下找到文件时告警 void UpdateAndWarnFileFindInDepBak(CSimpleStringA& newDepPath, const char* filename, DWORD userCode) { CSimpleStringA strOldPath; if (!ExistsFileA(newDepPath.GetData())) { ErrorCodeEnum eErrOld = this->GetEntityBase()->GetFunction()->GetPath("DepBak", strOldPath); if (eErrOld != Error_Succeed) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode(RTAERR_GETPATH_FAILED)("Get [DepBak] Path failed! errcode:%s.", SpStrError(eErrOld)); } strOldPath = CSimpleStringA::Format("%s" SPLIT_SLASH_STR "%s", strOldPath.GetData(), filename); if (ExistsFileA(strOldPath.GetData())) { newDepPath = strOldPath; CSimpleStringA warnMsg = CSimpleStringA::Format("Find %s in OLD dep path!", strOldPath.GetData()); LogWarn(Severity_Middle, Error_Unexpect, userCode, warnMsg.GetData()); } } } ErrorCodeEnum LoadUpAdapterLibrary(const CSimpleStringA& customDllPath = "") { m_hDevHelper.SetAdapterName(this->GetEntityBase()->GetEntityName()); ErrorCodeEnum rc = m_hDevHelper.LoadUp(customDllPath.IsNullOrEmpty() ? m_adapterInfo.adapterFilePath : customDllPath); return rc; } /*fulfill adapter elem, open param and adapter file name&absolute path */ void FulfillAdapterInfoFrom(const VendorLibInfo& vendorLib) { m_adapterInfo.strVendor = vendorLib.strVendor; m_adapterInfo.strVersion = vendorLib.strVersion; m_adapterInfo.strBatch = vendorLib.strBatch; m_adapterInfo.strPureAdapterName = vendorLib.strFileValue; CSmartPointer spConfigRoot; ErrorCodeEnum ec = this->GetEntityBase()->GetFunction()->OpenConfig(Config_Root, spConfigRoot); if (ec != Error_Succeed) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode(RTAERR_CONFIG_OPEN_FAILED)("Open Config_Root failed: %s.", SpStrError(ec)); return; } CSimpleStringA entityName(this->GetEntityBase()->GetEntityName()); if (entityName.Compare("CardIssuerStore", true) == 0 || entityName.Compare("CardIssuerStand", true) == 0) { entityName = "CardIssuer"; } CSimpleStringA sectionName = CSimpleStringA::Format("Device.%s", entityName.GetData()); CSimpleStringA csPort(true), csBaudrate(true); spConfigRoot->ReadConfigValue(sectionName.GetData(), "Port", csPort); spConfigRoot->ReadConfigValue(sectionName.GetData(), "Baudrate", csBaudrate); m_adapterInfo.strPort = csPort; m_adapterInfo.strBaudrate = csBaudrate; CSimpleStringA csPortNum(true); if (!entityName.Compare("Gpio")) { spConfigRoot->ReadConfigValue(sectionName.GetData(), "PortNum", csPortNum); m_adapterInfo.strPortNum = csPortNum; } m_adapterInfo.adapterFileName = vendorLib.toLibNameString(); CSimpleStringA strDepPath(true); ec = this->GetEntityBase()->GetFunction()->GetPath("Dep", strDepPath); if (IS_FAILURED(ec)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode(RTAERR_GETPATH_FAILED)("GetPath for Dep failed: %s.", SpStrError(ec)); } m_adapterInfo.adapterFilePath = CSimpleStringA::Format("%s" SPLIT_SLASH_STR "%s", (LPCTSTR)strDepPath, (LPCTSTR)m_adapterInfo.adapterFileName); } ErrorCodeEnum FulfillAdapterDevCategory() { if (!!m_hDevHelper) { ErrorCodeEnum result(Error_Succeed); DevCategoryInfo devCat; ZeroMemory(devCat.szModel, sizeof(devCat.szModel)); ZeroMemory(devCat.szType, sizeof(devCat.szType)); ZeroMemory(devCat.szVendor, sizeof(devCat.szVendor)); result = m_hDevHelper->GetDevCategory(devCat); /** 这里不加错误的判断,让硬件实体调用方去兜 [Gifur@2025714]*/ if (IS_SUCCEED(result)) { m_adapterInfo.FulfillCategoryInfo(devCat); } return result; } return Error_InvalidState; } virtual ErrorCodeEnum PreOpenDevice() { return Error_Succeed; } virtual ErrorCodeEnum ToOpenDevice() { return Error_NotImpl; } virtual ErrorCodeEnum PostOpenDevice() { return Error_Succeed; } //暂时未使用 ErrorCodeEnum OpenDevice() { if (m_bOpening) { return Error_Pending; } if (m_bOpened) { return Error_DevAlreadyConnected; } m_bOpening = true; ErrorCodeEnum result = PreOpenDevice(); if (IS_SUCCEED(result)) { result = ToOpenDevice(); if (IS_SUCCEED(result)) { m_bOpened = true; result = PostOpenDevice(); } } m_bOpening = false; return result; } virtual void SetDevInitFlag(bool val = true) { m_bOpened = val; } bool GetDevInitFlag() const { return m_bOpened; } virtual void SetDevInitingFlag(bool val = true) { m_bOpening = val; } bool GetDevInitingFlag() const { return m_bOpening; } virtual void SetInWhatPage(int iPageType) { m_iInWhatPage = iPageType; } void OnUIState4SetWhatPage(const char* pcszValue) { if (pcszValue != NULL && strlen(pcszValue) > 0) { bool trigger(false); UiState2WhatPage(pcszValue); if (m_preUIState != pcszValue[0]) { if (pcszValue[0] == 'M') { trigger = true; } m_preUIState = pcszValue[0]; } if (trigger) { this->PostEventFIFO(new FSMEvent(EVT_MAINPAGE_DISPLAY)); } } } virtual DevStateEnum GetDevState() const { return m_eDevState; } void SetDevState(DevStateEnum val = DEVICE_STATUS_NORMAL) { m_eDevState = val; } public: bool m_bOpened; bool m_bOpening; protected: DevAdptLibHelper m_hDevHelper; DevEntityErrorCode m_entCode; int m_iInWhatPage/*在哪个页面,区分首页,用户桌面,其他页*/; ErrorPackageEx m_errPkgEx; AdapterInfo m_adapterInfo; DevStateEnum m_eDevState; void __PostInit() override { if (this->GetEntityBase() != NULL) { CSimpleStringA uiState(true); auto err = this->GetEntityBase()->GetFunction()->GetSysVar("UIState", uiState); if (err == Error_Succeed && !uiState.IsNullOrEmpty()) { UiState2WhatPage(uiState); } else if (err != Error_Succeed) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode(RTAERR_SYSVAR_GET_FAILED)("Get sysVar for UIState failed:%s", SpStrError(err)); } } } void UpdateEntityIDIfZero() { if (m_entCode.dwEntityId == 0) { UpdateEntityID(); } } void UpdateEntityID() { CEntityStaticInfo esi = { 0 }; ErrorCodeEnum ec = this->GetEntityBase()->GetFunction()->GetEntityStaticInfo(this->GetEntityBase()->GetEntityName(), esi); if (ec == Error_Succeed) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("wEntityDevelopID: 0x%X", esi.wEntityDevelopID); m_entCode.ResetWithEntityID(esi.wEntityDevelopID); } } DWORD GetEntityID() { UpdateEntityIDIfZero(); return m_entCode.dwEntityId; } DWORD UpdateDEC(DWORD dwVal = 0) { UpdateEntityIDIfZero(); /** 14 is for entity define, FC(6bit) is reserved*/ int reserved = (dwVal & 0xFC000) >> 14; m_entCode.SetDevCode(dwVal, reserved); return GetDEC(); } DWORD GetDEC() const { return m_entCode.GetCompleteErrorCode(); } DWORD GetAlarmDEC(DWORD dwValue = 0) { if (dwValue > 0) UpdateDEC(dwValue); //if have been set ErrorCode of entity defined (not device),use it directly DWORD dwCode = 0; //if ((m_entCode.dwVendorErroCode >> 20) == m_entCode.dwEntityId) if(IsEntityIDSettle(m_entCode.dwVendorErroCode)) dwCode = m_entCode.dwVendorErroCode; else dwCode = HARDWARE_ENTITY_MAKE_ERRORCODE_TO_BUSINESS(m_entCode); return dwCode; } void ClearRelatedDEC() { UpdateDEC(); } bool IsEntityIDSettle(const DWORD& dwVal) const { return ((dwVal >> 20) == m_entCode.dwEntityId); } /** 目前没有调用方,暂时注释 [Gifur@2025711]*/ /* static void GetFileSizeAndCalcHashValue(const char* fileName, int& fileSize, BYTE fileHash[32]) { HANDLE hFile; hFile = CreateFile(fileName, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { fileSize = 0; return; } fileSize = GetFileSize(hFile, NULL); CloseHandle(hFile); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to calc vendor dll hash"); SM3File(const_cast(fileName), fileHash); return; }*/ virtual bool IsInBusiness() const { return (m_iInWhatPage == PageType_Other); } virtual void OnHardwareShakeHand(CSmartPointer pTransactionContext); private: void UiState2WhatPage(const char* pcszValue) { //增加页面位置判断 if (_strnicmp(pcszValue, "M", strlen("M")) == 0) { SetInWhatPage(PageType_MainPage); } else if (_strnicmp(pcszValue, "U", strlen("U")) == 0) { SetInWhatPage(PageType_UserDesktop); } else if (_strnicmp(pcszValue, "X", strlen("X")) != 0) { SetInWhatPage(PageType_Other); } } private: char m_preUIState; }; template inline ErrorCodeEnum CCommDevFSM::GetAndSplitDevErrInfo( CSimpleStringA& csErrMsg, WORD& wdDevErrCode, LPCTSTR lpszFuncNameForDisplay) { csErrMsg = ""; wdDevErrCode = 0; BOOL bDisplayFunName = TRUE; if (lpszFuncNameForDisplay == NULL || strlen(lpszFuncNameForDisplay) == 0) { bDisplayFunName = FALSE; } if (!m_hDevHelper) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setResultCode(DEVICE_FSM_DEVOBJ_NULLPTR)("inst occurs nullptr !!!"); return Error_Param; } DevErrorInfo devErrInfo; ZeroMemory(&devErrInfo, sizeof(DevErrorInfo)); ErrorCodeEnum erroCode = m_hDevHelper->GetLastErr(devErrInfo); if (erroCode == Error_Succeed) { if (strlen(devErrInfo.szErrMsg) > 0) { csErrMsg = devErrInfo.szErrMsg; } if (devErrInfo.dwErrMsgLen > MAX_DEV_ERROR_MSG_LEN) { wdDevErrCode = (WORD)((devErrInfo.dwErrMsgLen >> 16) & 0x0000FFFF); } } else { if (bDisplayFunName) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)/*.setAPI("DevAdapter::GetLastErr")不纳入适配器消费,因为不好分配RTA,只做调研*/ .setResultCode(DEVICE_FSM_DEVGETLE_FAILED)("GetLastErr after %s failed returned: %s",lpszFuncNameForDisplay, SpStrError(erroCode)); csErrMsg = CSimpleStringA::Format("Invoke <%s> failed", lpszFuncNameForDisplay); } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)/*.setAPI("DevAdapter::GetLastErr")不纳入适配器消费,因为不好分配RTA,只做调研*/ .setResultCode(DEVICE_FSM_DEVGETLE_FAILED)("GetLastErr failed returned: %s", SpStrError(erroCode)); } } /** reset vendor device error code to stop reporting to alarm [12/11/2020 Gifur] */ wdDevErrCode = 0; return erroCode; } template void CCommDevFSM::OnHardwareShakeHand(CSmartPointer pTransactionContext) { if (m_eDevState == DEVICE_STATUS_NORMAL) pTransactionContext->SendAnswer(Error_Succeed); else { if (m_bOpening) pTransactionContext->SendAnswer(Error_Succeed); else if (!m_bOpened) pTransactionContext->SendAnswer(Error_DevNotAvailable); else pTransactionContext->SendAnswer(Error_InvalidState); } } #endif /*_COMM_DEVICE_FSM_BASE_HPP_*/