1 /******************************************************************************
2 *
3 * Copyright 2020, 2022-2023 NXP
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #define LOG_TAG "weaver-impl"
20 #include <weaver-impl.h>
21 #include <weaver_parser-impl.h>
22 #include <weaver_transport-impl.h>
23 #include <weaver_utils.h>
24
25 WeaverImpl *WeaverImpl::s_instance = NULL;
26 std::once_flag WeaverImpl::s_instanceFlag;
27
28 /**
29 * \brief static function to get the singleton instance of WeaverImpl class
30 *
31 * \retval instance of WeaverImpl.
32 */
getInstance()33 WeaverImpl *WeaverImpl::getInstance() {
34 /* call_once c++11 api which executes the passed function ptr exactly once,
35 * even if called concurrently, from several threads
36 */
37 std::call_once(s_instanceFlag, &WeaverImpl::createInstance);
38 return s_instance;
39 }
40
41 /* Private function to create the instance of self class
42 * Same will be used for std::call_once
43 */
createInstance()44 void WeaverImpl::createInstance() {
45 LOG_D(TAG, "Entry");
46 s_instance = new WeaverImpl;
47 }
48
49 /**
50 * \brief Function to initialize Weaver Interface
51 *
52 * \retval This function return Weaver_STATUS_OK (0) in case of success
53 * In case of failure returns other Status_Weaver.
54 */
Init()55 Status_Weaver WeaverImpl::Init() {
56 LOG_D(TAG, "Entry");
57 mTransport = WeaverTransportImpl::getInstance();
58 mParser = WeaverParserImpl::getInstance();
59 RETURN_IF_NULL(mTransport, WEAVER_STATUS_FAILED, "Transport is NULL");
60 RETURN_IF_NULL(mParser, WEAVER_STATUS_FAILED, "Parser is NULL");
61 std::vector<std::vector<uint8_t>> aid;
62 mParser->getAppletId(aid);
63 if (!mTransport->Init(std::move(aid))) {
64 LOG_E(TAG, "Not able to Initialize Transport Interface");
65 LOG_D(TAG, "Exit : FAILED");
66 return WEAVER_STATUS_FAILED;
67 }
68 LOG_D(TAG, "Exit : SUCCESS");
69 return WEAVER_STATUS_OK;
70 }
71
72 /**
73 * \brief Function to read slot information
74 * \param[out] slotInfo - slot information values read out
75 *
76 * \retval This function return Weaver_STATUS_OK (0) in case of success
77 * In case of failure returns other Status_Weaver errorcodes.
78 */
GetSlots(SlotInfo & slotInfo)79 Status_Weaver WeaverImpl::GetSlots(SlotInfo &slotInfo) {
80 LOG_D(TAG, "Entry");
81 RETURN_IF_NULL(mTransport, WEAVER_STATUS_FAILED, "Transport is NULL");
82 RETURN_IF_NULL(mParser, WEAVER_STATUS_FAILED, "Parser is NULL");
83 Status_Weaver status = WEAVER_STATUS_FAILED;
84 std::vector<uint8_t> getSlotCmd;
85 std::vector<uint8_t> resp;
86 /* transport library don't require open applet
87 * open will be done as part of send */
88 if (mParser->FrameGetSlotCmd(getSlotCmd) &&
89 mTransport->Send(getSlotCmd, resp)) {
90 status = WEAVER_STATUS_OK;
91 } else {
92 LOG_E(TAG, "Failed to perform getSlot Request");
93 }
94 #ifndef INTERVAL_TIMER
95 if (!close()) {
96 // Channel Close Failed
97 LOG_E(TAG, "Failed to Close Channel");
98 }
99 #endif
100 if (status == WEAVER_STATUS_OK) {
101 status = mParser->ParseSlotInfo(std::move(resp), slotInfo);
102 LOG_D(TAG, "Total Slots (%u) ", slotInfo.slots);
103 } else {
104 LOG_E(TAG, "Failed Parsing getSlot Response");
105 }
106 LOG_D(TAG, "Exit");
107 return status;
108 }
109
110 /* Internal close api for transport close */
close()111 bool WeaverImpl::close() {
112 LOG_D(TAG, "Entry");
113 bool status = true;
114 RETURN_IF_NULL(mTransport, WEAVER_STATUS_FAILED, "Transport is NULL");
115 if (!mTransport->CloseApplet()) {
116 status = false;
117 }
118 LOG_D(TAG, "Exit");
119 return status;
120 }
121
122 /**
123 * \brief Function to read value of specific key & slotId
124 * \param[in] slotId - input slotId which's information to be read
125 * \param[in] key - input key which's information to be read
126 * \param[out] readRespInfo - read information values to be read out
127 *
128 * \retval This function return Weaver_STATUS_OK (0) in case of success
129 * In case of failure returns other Status_Weaver errorcodes.
130 */
Read(uint32_t slotId,const std::vector<uint8_t> & key,ReadRespInfo & readRespInfo)131 Status_Weaver WeaverImpl::Read(uint32_t slotId, const std::vector<uint8_t> &key,
132 ReadRespInfo &readRespInfo) {
133 LOG_D(TAG, "Entry");
134 RETURN_IF_NULL(mTransport, WEAVER_STATUS_FAILED, "Transport is NULL");
135 RETURN_IF_NULL(mParser, WEAVER_STATUS_FAILED, "Parser is NULL");
136 Status_Weaver status = WEAVER_STATUS_FAILED;
137 std::vector<uint8_t> cmd;
138 std::vector<uint8_t> resp;
139 std::vector<uint8_t> aid;
140 /* transport library don't require open applet
141 * open will be done as part of send */
142 LOG_D(TAG, "Read from Slot (%u)", slotId);
143 if (mParser->FrameReadCmd(slotId, key, cmd) &&
144 mTransport->Send(cmd, resp)) {
145 status = WEAVER_STATUS_OK;
146 }
147 if (status == WEAVER_STATUS_OK) {
148 status = mParser->ParseReadInfo(resp, readRespInfo);
149 if (status == WEAVER_STATUS_THROTTLE ||
150 status == WEAVER_STATUS_INCORRECT_KEY) {
151 cmd.clear();
152 resp.clear();
153 if (mParser->FrameGetDataCmd(WeaverParserImpl::sThrottleGetDataP1, (uint8_t)slotId, cmd) &&
154 (mTransport->Send(cmd, resp))) {
155 GetDataRespInfo getDataInfo;
156 if (mParser->ParseGetDataInfo(std::move(resp), getDataInfo) == WEAVER_STATUS_OK) {
157 /* convert timeout from getDataInfo sec to millisecond assign same to read response */
158 readRespInfo.timeout = (getDataInfo.timeout * 1000);
159 if (getDataInfo.timeout > 0) {
160 status = WEAVER_STATUS_THROTTLE;
161 }
162 }
163 }
164 }
165 } else {
166 LOG_E(TAG, "Failed to perform Read Request for slot (%u)", slotId);
167 }
168 #ifndef INTERVAL_TIMER
169 if (!close()) {
170 // Channel Close Failed
171 LOG_E(TAG, "Failed to Close Channel");
172 }
173 #endif
174 LOG_D(TAG, "Exit");
175 return status;
176 }
177
178 /**
179 * \brief Function to write value to specific key & slotId
180 * \param[in] slotId - input slotId where value to be write
181 * \param[in] key - input key where value to be write
182 * \param[in] value - input value which will be written
183 *
184 * \retval This function return Weaver_STATUS_OK (0) in case of success
185 * In case of failure returns other Status_Weaver.
186 */
Write(uint32_t slotId,const std::vector<uint8_t> & key,const std::vector<uint8_t> & value)187 Status_Weaver WeaverImpl::Write(uint32_t slotId,
188 const std::vector<uint8_t> &key,
189 const std::vector<uint8_t> &value) {
190 LOG_D(TAG, "Entry");
191 RETURN_IF_NULL(mTransport, WEAVER_STATUS_FAILED, "Transport is NULL");
192 RETURN_IF_NULL(mParser, WEAVER_STATUS_FAILED, "Parser is NULL");
193 Status_Weaver status = WEAVER_STATUS_FAILED;
194 std::vector<uint8_t> readCmd;
195 std::vector<uint8_t> resp;
196 std::vector<uint8_t> aid;
197 /* transport library don't require open applet
198 * open will be done as part of send */
199 LOG_D(TAG, "Write to Slot (%u)", slotId);
200 if (mParser->FrameWriteCmd(slotId, key, value, readCmd) &&
201 mTransport->Send(readCmd, resp)) {
202 status = WEAVER_STATUS_OK;
203 }
204 #ifndef INTERVAL_TIMER
205 if (!close()) {
206 LOG_E(TAG, "Failed to Close Channel");
207 // Channel Close Failed
208 }
209 #endif
210 if (status != WEAVER_STATUS_OK || (!mParser->isSuccess(std::move(resp)))) {
211 status = WEAVER_STATUS_FAILED;
212 }
213 LOG_D(TAG, "Exit");
214 return status;
215 }
216
217 /**
218 * \brief Function to de-initialize Weaver Interface
219 *
220 * \retval This function return Weaver_STATUS_OK (0) in case of success
221 * In case of failure returns other Status_Weaver.
222 */
DeInit()223 Status_Weaver WeaverImpl::DeInit() {
224 LOG_D(TAG, "Entry");
225 if (mTransport != NULL) {
226 mTransport->DeInit();
227 }
228 LOG_D(TAG, "Exit");
229 return WEAVER_STATUS_OK;
230 }
231