/****************************************************************************** * * Copyright 2020, 2022-2023 NXP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ #define LOG_TAG "weaver-impl" #include #include #include #include WeaverImpl *WeaverImpl::s_instance = NULL; std::once_flag WeaverImpl::s_instanceFlag; /** * \brief static function to get the singleton instance of WeaverImpl class * * \retval instance of WeaverImpl. */ WeaverImpl *WeaverImpl::getInstance() { /* call_once c++11 api which executes the passed function ptr exactly once, * even if called concurrently, from several threads */ std::call_once(s_instanceFlag, &WeaverImpl::createInstance); return s_instance; } /* Private function to create the instance of self class * Same will be used for std::call_once */ void WeaverImpl::createInstance() { LOG_D(TAG, "Entry"); s_instance = new WeaverImpl; } /** * \brief Function to initialize Weaver Interface * * \retval This function return Weaver_STATUS_OK (0) in case of success * In case of failure returns other Status_Weaver. */ Status_Weaver WeaverImpl::Init() { LOG_D(TAG, "Entry"); mTransport = WeaverTransportImpl::getInstance(); mParser = WeaverParserImpl::getInstance(); RETURN_IF_NULL(mTransport, WEAVER_STATUS_FAILED, "Transport is NULL"); RETURN_IF_NULL(mParser, WEAVER_STATUS_FAILED, "Parser is NULL"); std::vector> aid; mParser->getAppletId(aid); if (!mTransport->Init(std::move(aid))) { LOG_E(TAG, "Not able to Initialize Transport Interface"); LOG_D(TAG, "Exit : FAILED"); return WEAVER_STATUS_FAILED; } LOG_D(TAG, "Exit : SUCCESS"); return WEAVER_STATUS_OK; } /** * \brief Function to read slot information * \param[out] slotInfo - slot information values read out * * \retval This function return Weaver_STATUS_OK (0) in case of success * In case of failure returns other Status_Weaver errorcodes. */ Status_Weaver WeaverImpl::GetSlots(SlotInfo &slotInfo) { LOG_D(TAG, "Entry"); RETURN_IF_NULL(mTransport, WEAVER_STATUS_FAILED, "Transport is NULL"); RETURN_IF_NULL(mParser, WEAVER_STATUS_FAILED, "Parser is NULL"); Status_Weaver status = WEAVER_STATUS_FAILED; std::vector getSlotCmd; std::vector resp; /* transport library don't require open applet * open will be done as part of send */ if (mParser->FrameGetSlotCmd(getSlotCmd) && mTransport->Send(getSlotCmd, resp)) { status = WEAVER_STATUS_OK; } else { LOG_E(TAG, "Failed to perform getSlot Request"); } #ifndef INTERVAL_TIMER if (!close()) { // Channel Close Failed LOG_E(TAG, "Failed to Close Channel"); } #endif if (status == WEAVER_STATUS_OK) { status = mParser->ParseSlotInfo(std::move(resp), slotInfo); LOG_D(TAG, "Total Slots (%u) ", slotInfo.slots); } else { LOG_E(TAG, "Failed Parsing getSlot Response"); } LOG_D(TAG, "Exit"); return status; } /* Internal close api for transport close */ bool WeaverImpl::close() { LOG_D(TAG, "Entry"); bool status = true; RETURN_IF_NULL(mTransport, WEAVER_STATUS_FAILED, "Transport is NULL"); if (!mTransport->CloseApplet()) { status = false; } LOG_D(TAG, "Exit"); return status; } /** * \brief Function to read value of specific key & slotId * \param[in] slotId - input slotId which's information to be read * \param[in] key - input key which's information to be read * \param[out] readRespInfo - read information values to be read out * * \retval This function return Weaver_STATUS_OK (0) in case of success * In case of failure returns other Status_Weaver errorcodes. */ Status_Weaver WeaverImpl::Read(uint32_t slotId, const std::vector &key, ReadRespInfo &readRespInfo) { LOG_D(TAG, "Entry"); RETURN_IF_NULL(mTransport, WEAVER_STATUS_FAILED, "Transport is NULL"); RETURN_IF_NULL(mParser, WEAVER_STATUS_FAILED, "Parser is NULL"); Status_Weaver status = WEAVER_STATUS_FAILED; std::vector cmd; std::vector resp; std::vector aid; /* transport library don't require open applet * open will be done as part of send */ LOG_D(TAG, "Read from Slot (%u)", slotId); if (mParser->FrameReadCmd(slotId, key, cmd) && mTransport->Send(cmd, resp)) { status = WEAVER_STATUS_OK; } if (status == WEAVER_STATUS_OK) { status = mParser->ParseReadInfo(resp, readRespInfo); if (status == WEAVER_STATUS_THROTTLE || status == WEAVER_STATUS_INCORRECT_KEY) { cmd.clear(); resp.clear(); if (mParser->FrameGetDataCmd(WeaverParserImpl::sThrottleGetDataP1, (uint8_t)slotId, cmd) && (mTransport->Send(cmd, resp))) { GetDataRespInfo getDataInfo; if (mParser->ParseGetDataInfo(std::move(resp), getDataInfo) == WEAVER_STATUS_OK) { /* convert timeout from getDataInfo sec to millisecond assign same to read response */ readRespInfo.timeout = (getDataInfo.timeout * 1000); if (getDataInfo.timeout > 0) { status = WEAVER_STATUS_THROTTLE; } } } } } else { LOG_E(TAG, "Failed to perform Read Request for slot (%u)", slotId); } #ifndef INTERVAL_TIMER if (!close()) { // Channel Close Failed LOG_E(TAG, "Failed to Close Channel"); } #endif LOG_D(TAG, "Exit"); return status; } /** * \brief Function to write value to specific key & slotId * \param[in] slotId - input slotId where value to be write * \param[in] key - input key where value to be write * \param[in] value - input value which will be written * * \retval This function return Weaver_STATUS_OK (0) in case of success * In case of failure returns other Status_Weaver. */ Status_Weaver WeaverImpl::Write(uint32_t slotId, const std::vector &key, const std::vector &value) { LOG_D(TAG, "Entry"); RETURN_IF_NULL(mTransport, WEAVER_STATUS_FAILED, "Transport is NULL"); RETURN_IF_NULL(mParser, WEAVER_STATUS_FAILED, "Parser is NULL"); Status_Weaver status = WEAVER_STATUS_FAILED; std::vector readCmd; std::vector resp; std::vector aid; /* transport library don't require open applet * open will be done as part of send */ LOG_D(TAG, "Write to Slot (%u)", slotId); if (mParser->FrameWriteCmd(slotId, key, value, readCmd) && mTransport->Send(readCmd, resp)) { status = WEAVER_STATUS_OK; } #ifndef INTERVAL_TIMER if (!close()) { LOG_E(TAG, "Failed to Close Channel"); // Channel Close Failed } #endif if (status != WEAVER_STATUS_OK || (!mParser->isSuccess(std::move(resp)))) { status = WEAVER_STATUS_FAILED; } LOG_D(TAG, "Exit"); return status; } /** * \brief Function to de-initialize Weaver Interface * * \retval This function return Weaver_STATUS_OK (0) in case of success * In case of failure returns other Status_Weaver. */ Status_Weaver WeaverImpl::DeInit() { LOG_D(TAG, "Entry"); if (mTransport != NULL) { mTransport->DeInit(); } LOG_D(TAG, "Exit"); return WEAVER_STATUS_OK; }