| /****************************************************************************** |
| * |
| * 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 <weaver-impl.h> |
| #include <weaver_parser-impl.h> |
| #include <weaver_transport-impl.h> |
| #include <weaver_utils.h> |
| |
| 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<std::vector<uint8_t>> 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<uint8_t> getSlotCmd; |
| std::vector<uint8_t> 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<uint8_t> &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<uint8_t> cmd; |
| std::vector<uint8_t> resp; |
| std::vector<uint8_t> 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<uint8_t> &key, |
| const std::vector<uint8_t> &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<uint8_t> readCmd; |
| std::vector<uint8_t> resp; |
| std::vector<uint8_t> 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; |
| } |