1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "tag_host.h"
16 #include <thread>
17 #include <unistd.h>
18 #include "loghelper.h"
19 #include "nfa_api.h"
20 #include "nfc_sdk_common.h"
21 #include "taginfo.h"
22 #include "tag_native_impl.h"
23 #include "tag_nci_adapter_rw.h"
24 #include "tag_nci_adapter_common.h"
25 
26 namespace OHOS {
27 namespace NFC {
28 namespace NCI {
29 static const uint32_t DEFAULT_VALUE = 0xFFFF;
30 OHOS::NFC::SynchronizeEvent TagHost::fieldCheckWatchDog_;
TagHost(const std::vector<int> & tagTechList,const std::vector<uint32_t> & tagRfDiscIdList,const std::vector<uint32_t> & tagActivatedProtocols,const std::string & tagUid,const std::vector<std::string> & tagPollBytes,const std::vector<std::string> & tagActivatedBytes,const uint32_t connectedTechIndex)31 TagHost::TagHost(const std::vector<int>& tagTechList,
32                  const std::vector<uint32_t>& tagRfDiscIdList,
33                  const std::vector<uint32_t>& tagActivatedProtocols,
34                  const std::string& tagUid,
35                  const std::vector<std::string>& tagPollBytes,
36                  const std::vector<std::string>& tagActivatedBytes,
37                  const uint32_t connectedTechIndex)
38     : tagTechList_(std::move(tagTechList)),
39       tagRfDiscIdList_(std::move(tagRfDiscIdList)),
40       tagRfProtocols_(std::move(tagActivatedProtocols)),
41       tagUid_(tagUid),
42       tagPollBytes_(std::move(tagPollBytes)),
43       tagActivatedBytes_(std::move(tagActivatedBytes)),
44       connectedTagDiscId_(DEFAULT_VALUE),
45       connectedTechIndex_(connectedTechIndex),
46       isTagFieldOn_(true),
47       isFieldChecking_(false),
48       isPauseFieldChecking_(false),
49       isSkipNextFieldChecking_(false),
50       addNdefTech_(false)
51 {
52 }
53 
~TagHost()54 TagHost::~TagHost()
55 {
56     tagTechList_.clear();
57     technologyList_.clear();
58     tagRfDiscIdList_.clear();
59     tagRfProtocols_.clear();
60     tagPollBytes_.clear();
61     tagActivatedBytes_.clear();
62 }
63 
Connect(int technology)64 bool TagHost::Connect(int technology)
65 {
66     DebugLog("TagHost::Connect tech = %{public}d", technology);
67     PauseFieldChecking();
68     std::lock_guard<std::mutex> lock(mutex_);
69     tNFA_STATUS status = NFA_STATUS_FAILED;
70     bool result = false;
71     for (std::size_t i = 0; i < tagTechList_.size(); i++) {
72         if (technology != tagTechList_[i]) {
73             continue;
74         }
75         // try connect the tag
76         if (connectedTagDiscId_ != tagRfDiscIdList_[i]) {
77             status = TagNciAdapterRw::GetInstance().Connect(i);
78         } else {
79             if (technology == static_cast<int>(KITS::TagTechnology::NFC_NDEF_TECH)) {
80                 // special for ndef
81                 i = 0;
82             }
83             status = TagNciAdapterRw::GetInstance().Connect(i);
84         }
85         if (status == NFA_STATUS_OK) {
86             DebugLog("TagHost::Connect, connected to index = %{public}zu", i);
87             connectedTagDiscId_ = tagRfDiscIdList_[i];
88             connectedTechIndex_ = static_cast<uint32_t>(i);
89             isTagFieldOn_ = true;
90             result = true;
91         }
92         break;
93     }
94     ResumeFieldChecking();
95     DebugLog("TagHost::Connect exit, result = %{public}d", result);
96     return result;
97 }
98 
Disconnect()99 bool TagHost::Disconnect()
100 {
101     DebugLog("TagHost::Disconnect");
102     std::lock_guard<std::mutex> lock(mutex_);
103     connectedTagDiscId_ = DEFAULT_VALUE;
104     connectedTechIndex_ = DEFAULT_VALUE;
105     StopFieldCheckingInner();
106     DebugLog("TagHost::Disconnect exit");
107     return true;
108 }
109 
Reconnect()110 bool TagHost::Reconnect()
111 {
112     DebugLog("TagHost::Reconnect");
113     if (connectedTechIndex_ == DEFAULT_VALUE) {
114         ErrorLog("TagHost::Reconnect invalid tech index");
115         return true;
116     }
117     PauseFieldChecking();
118     std::lock_guard<std::mutex> lock(mutex_);
119     bool result = TagNciAdapterRw::GetInstance().Reconnect();
120     ResumeFieldChecking();
121     DebugLog("TagHost::Reconnect exit, result = %{public}d", result);
122     return result;
123 }
124 
Transceive(const std::string & request,std::string & response)125 int TagHost::Transceive(const std::string& request, std::string& response)
126 {
127     DebugLog("TagHost::Transceive");
128     PauseFieldChecking();
129     std::lock_guard<std::mutex> lock(mutex_);
130     int status = TagNciAdapterRw::GetInstance().Transceive(request, response);
131     ResumeFieldChecking();
132     DebugLog("TagHost::Transceive exit, result = %{public}d", status);
133     return status;
134 }
135 
FieldOnCheckingThread()136 bool TagHost::FieldOnCheckingThread()
137 {
138     DebugLog("TagHost::FieldOnCheckingThread");
139     PauseFieldChecking();
140     std::lock_guard<std::mutex> lock(mutex_);
141     isTagFieldOn_ = TagNciAdapterRw::GetInstance().IsTagFieldOn();
142     ResumeFieldChecking();
143     return isTagFieldOn_;
144 }
145 
IsTagFieldOn()146 bool TagHost::IsTagFieldOn()
147 {
148     DebugLog("TagHost::IsTagFieldOn, result = %{public}d", isTagFieldOn_);
149     return isTagFieldOn_;
150 }
151 
PauseFieldChecking()152 void TagHost::PauseFieldChecking()
153 {
154     DebugLog("TagHost::PauseFieldChecking");
155     isPauseFieldChecking_ = true;
156     isSkipNextFieldChecking_ = true;
157 }
158 
ResumeFieldChecking()159 void TagHost::ResumeFieldChecking()
160 {
161     DebugLog("TagHost::ResumeFieldChecking");
162     isPauseFieldChecking_ = false;
163     isSkipNextFieldChecking_ = true;
164 }
165 
FieldCheckingThread(uint32_t delayedMs)166 void TagHost::FieldCheckingThread(uint32_t delayedMs)
167 {
168     while (isFieldChecking_) {
169         NFC::SynchronizeGuard guard(fieldCheckWatchDog_);
170         if (isPauseFieldChecking_) {
171             // only wait when checking is paused
172             fieldCheckWatchDog_.Wait(delayedMs);
173             continue;
174         } else {
175             isSkipNextFieldChecking_ = false;
176         }
177         fieldCheckWatchDog_.Wait(delayedMs);
178         DebugLog("FieldCheckingThread, isSkipNextFieldChecking_ = %{public}d", isSkipNextFieldChecking_);
179         if (isSkipNextFieldChecking_) {
180             // if field checking is paused or resumed in this interval, no checking this time
181             continue;
182         }
183         bool result = TagNciAdapterRw::GetInstance().IsTagFieldOn();
184         DebugLog("FieldCheckingThread::is tag field on = %{public}d", result);
185         if (!result) {
186             DebugLog("FieldCheckingThread::Tag lost...");
187             break;
188         }
189     }
190     isTagFieldOn_ = false;
191     TagNciAdapterCommon::GetInstance().ResetTag();
192     TagNciAdapterRw::GetInstance().Disconnect();
193     if (isFieldChecking_ && tagRfDiscIdList_.size() > 0) {
194         DebugLog("FieldCheckingThread::Disconnect callback %{public}d", tagRfDiscIdList_[0]);
195         TagNativeImpl::GetInstance().OnTagLost(tagRfDiscIdList_[0]);
196     }
197     DebugLog("FieldCheckingThread::End Field Checking");
198 }
199 
StartFieldOnChecking(uint32_t delayedMs)200 void TagHost::StartFieldOnChecking(uint32_t delayedMs)
201 {
202     DebugLog("TagHost::StartFieldOnChecking");
203     isTagFieldOn_ = true;
204     isFieldChecking_ = true;
205     isSkipNextFieldChecking_ = false;
206     isPauseFieldChecking_ = false;
207     if (delayedMs <= 0) {
208         delayedMs = DEFAULT_PRESENCE_CHECK_WATCH_DOG_TIMEOUT;
209     }
210     std::thread([this, delayedMs]() { this->FieldCheckingThread(delayedMs); }).detach();
211 }
212 
StopFieldChecking()213 void TagHost::StopFieldChecking()
214 {
215     DebugLog("TagHost::StopFieldChecking");
216     if (!IsTagFieldOn()) {
217         InfoLog("TagHost::StopFieldChecking, no tag field on");
218         return;
219     }
220     Disconnect();
221 }
222 
StopFieldCheckingInner()223 void TagHost::StopFieldCheckingInner()
224 {
225     // shoule add lock mutex where the function is involked
226     DebugLog("TagHost::StopFeildCheckingInner");
227     NFC::SynchronizeGuard guard(fieldCheckWatchDog_);
228     isFieldChecking_ = false;
229     isSkipNextFieldChecking_ = true;
230     fieldCheckWatchDog_.NotifyOne();
231 }
232 
SetTimeout(uint32_t timeout,int technology)233 void TagHost::SetTimeout(uint32_t timeout, int technology)
234 {
235     DebugLog("TagHost::SetTimeout");
236     TagNciAdapterRw::GetInstance().SetTimeout(timeout, technology);
237 }
238 
GetTimeout(uint32_t technology)239 uint32_t TagHost::GetTimeout(uint32_t technology)
240 {
241     DebugLog("TagHost::GetTimeout, technology = %{public}d", technology);
242     return TagNciAdapterRw::GetInstance().GetTimeout(technology);
243 }
244 
ResetTimeout()245 void TagHost::ResetTimeout()
246 {
247     DebugLog("TagHost::ResetTimeout");
248     TagNciAdapterCommon::GetInstance().ResetTimeout();
249 }
250 
GetTechList()251 std::vector<int> TagHost::GetTechList()
252 {
253     for (std::vector<int>::iterator it = tagTechList_.begin(); it != tagTechList_.end(); ++it) {
254         KITS::TagTechnology technology = KITS::TagTechnology::NFC_INVALID_TECH;
255         switch (*it) {
256             case TagNciAdapterCommon::TARGET_TYPE_ISO14443_3A:
257                 technology = KITS::TagTechnology::NFC_A_TECH;
258                 break;
259             case TagNciAdapterCommon::TARGET_TYPE_ISO14443_3B:
260                 technology = KITS::TagTechnology::NFC_B_TECH;
261                 break;
262             case TagNciAdapterCommon::TARGET_TYPE_ISO14443_4:
263                 technology = KITS::TagTechnology::NFC_ISODEP_TECH;
264                 break;
265             case TagNciAdapterCommon::TARGET_TYPE_FELICA:
266                 technology = KITS::TagTechnology::NFC_F_TECH;
267                 break;
268             case TagNciAdapterCommon::TARGET_TYPE_V:
269                 technology = KITS::TagTechnology::NFC_V_TECH;
270                 break;
271             case TagNciAdapterCommon::TARGET_TYPE_NDEF:
272                 technology = KITS::TagTechnology::NFC_NDEF_TECH;
273                 break;
274             case TagNciAdapterCommon::TARGET_TYPE_NDEF_FORMATABLE:
275                 technology = KITS::TagTechnology::NFC_NDEF_FORMATABLE_TECH;
276                 break;
277             case TagNciAdapterCommon::TARGET_TYPE_MIFARE_CLASSIC:
278                 technology = KITS::TagTechnology::NFC_MIFARE_CLASSIC_TECH;
279                 break;
280             case TagNciAdapterCommon::TARGET_TYPE_MIFARE_UL:
281                 technology = KITS::TagTechnology::NFC_MIFARE_ULTRALIGHT_TECH;
282                 break;
283             case TagNciAdapterCommon::TARGET_TYPE_UNKNOWN:
284                 break;
285             default:
286                 technology = KITS::TagTechnology::NFC_INVALID_TECH;
287                 break;
288         }
289         technologyList_.push_back(static_cast<int>(technology));
290     }
291     return technologyList_;
292 }
293 
RemoveTech(int tech)294 void TagHost::RemoveTech(int tech)
295 {
296     DebugLog("TagHost::RemoveTech");
297 }
298 
GetTagUid()299 std::string TagHost::GetTagUid()
300 {
301     return tagUid_;
302 }
303 
DoTargetTypeIso144433a(AppExecFwk::PacMap & pacMap,uint32_t index)304 void TagHost::DoTargetTypeIso144433a(AppExecFwk::PacMap &pacMap, uint32_t index)
305 {
306     std::string act = tagActivatedBytes_[index];
307     std::string poll = tagPollBytes_[index];
308     if (!(act.empty())) {
309         uint32_t sak = (KITS::NfcSdkCommon::GetByteFromHexStr(act, 0) & 0xff);
310         pacMap.PutIntValue(KITS::TagInfo::SAK, sak);
311         DebugLog("DoTargetTypeIso144433a SAK: 0x%{public}X", sak);
312     }
313     pacMap.PutStringValue(KITS::TagInfo::ATQA, poll);
314     DebugLog("DoTargetTypeIso144433a ATQA: %{public}s", poll.c_str());
315 }
316 
DoTargetTypeIso144433b(AppExecFwk::PacMap & pacMap,uint32_t index)317 void TagHost::DoTargetTypeIso144433b(AppExecFwk::PacMap &pacMap, uint32_t index)
318 {
319     std::string poll = tagPollBytes_[index];
320     if (poll.empty()) {
321         DebugLog("DoTargetTypeIso144433b poll empty");
322         return;
323     }
324 
325     if (KITS::NfcSdkCommon::GetHexStrBytesLen(poll) <
326         (NCI_APP_DATA_LENGTH + NCI_PROTOCOL_INFO_LENGTH) * KITS::HEX_BYTE_LEN) {
327         DebugLog("DoTargetTypeIso144433b poll.len: %{public}d", KITS::NfcSdkCommon::GetHexStrBytesLen(poll));
328         return;
329     }
330 
331     std::string appData = poll.substr(0, (NCI_APP_DATA_LENGTH * KITS::HEX_BYTE_LEN));
332     pacMap.PutStringValue(KITS::TagInfo::APP_DATA, appData);
333     DebugLog("ParseTechExtras::TARGET_TYPE_ISO14443_3B APP_DATA: %{public}s", appData.c_str());
334 
335     std::string protoInfo = poll.substr((NCI_APP_DATA_LENGTH * KITS::HEX_BYTE_LEN),
336                                         (NCI_PROTOCOL_INFO_LENGTH * KITS::HEX_BYTE_LEN));
337     pacMap.PutStringValue(KITS::TagInfo::PROTOCOL_INFO, protoInfo);
338     DebugLog("ParseTechExtras::TARGET_TYPE_ISO14443_3B PROTOCOL_INFO: %{public}s", protoInfo.c_str());
339 }
340 
DoTargetTypeIso144434(AppExecFwk::PacMap & pacMap,uint32_t index)341 void TagHost::DoTargetTypeIso144434(AppExecFwk::PacMap &pacMap, uint32_t index)
342 {
343     bool hasNfcA = false;
344     std::string act = tagActivatedBytes_[index];
345     for (std::size_t i = 0; i < tagTechList_.size(); i++) {
346         if (tagTechList_[i] == TagNciAdapterCommon::TARGET_TYPE_ISO14443_3A) {
347             hasNfcA = true;
348             break;
349         }
350     }
351     if (hasNfcA) {
352         pacMap.PutStringValue(KITS::TagInfo::HISTORICAL_BYTES, act);
353         DebugLog("DoTargetTypeIso144434::HISTORICAL_BYTES: %{public}s", act.c_str());
354     } else {
355         pacMap.PutStringValue(KITS::TagInfo::HILAYER_RESPONSE, act);
356         DebugLog("DoTargetTypeIso144434::HILAYER_RESPONSE: %{public}s", act.c_str());
357     }
358 }
359 
DoTargetTypeV(AppExecFwk::PacMap & pacMap,uint32_t index)360 void TagHost::DoTargetTypeV(AppExecFwk::PacMap &pacMap, uint32_t index)
361 {
362     std::string poll = tagPollBytes_[index];
363     if (poll.empty()) {
364         DebugLog("DoTargetTypeV poll empty");
365         return;
366     }
367 
368     if (KITS::NfcSdkCommon::GetHexStrBytesLen(poll) < NCI_POLL_LENGTH_MIN) {
369         DebugLog("DoTargetTypeV poll.len: %{public}d", KITS::NfcSdkCommon::GetHexStrBytesLen(poll));
370         return;
371     }
372 
373     // 1st byte is response flag, 2nd byte is dsf id.
374     pacMap.PutIntValue(KITS::TagInfo::RESPONSE_FLAGS, KITS::NfcSdkCommon::GetByteFromHexStr(poll, 0));
375     DebugLog("DoTargetTypeV::RESPONSE_FLAGS: %{public}d", KITS::NfcSdkCommon::GetByteFromHexStr(poll, 0));
376     pacMap.PutIntValue(KITS::TagInfo::DSF_ID, KITS::NfcSdkCommon::GetByteFromHexStr(poll, 1));
377     DebugLog("DoTargetTypeV::DSF_ID: %{public}d", KITS::NfcSdkCommon::GetByteFromHexStr(poll, 1));
378 }
379 
DoTargetTypeF(AppExecFwk::PacMap & pacMap,uint32_t index)380 void TagHost::DoTargetTypeF(AppExecFwk::PacMap &pacMap, uint32_t index)
381 {
382     std::string poll = tagPollBytes_[index];
383     if (poll.empty()) {
384         DebugLog("DoTargetTypeF poll empty");
385         return;
386     }
387 
388     if (KITS::NfcSdkCommon::GetHexStrBytesLen(poll) < SENSF_RES_LENGTH) {
389         DebugLog("DoTargetTypeF no ppm, poll.len: %{public}d", KITS::NfcSdkCommon::GetHexStrBytesLen(poll));
390         return;
391     }
392     pacMap.PutStringValue(KITS::TagInfo::NFCF_PMM, poll.substr(0, SENSF_RES_LENGTH)); // 8 bytes for ppm
393 
394     if (KITS::NfcSdkCommon::GetHexStrBytesLen(poll) < F_POLL_LENGTH) {
395         DebugLog("DoTargetTypeF no sc, poll.len: %{public}d", KITS::NfcSdkCommon::GetHexStrBytesLen(poll));
396         return;
397     }
398     pacMap.PutStringValue(KITS::TagInfo::NFCF_SC, poll.substr(SENSF_RES_LENGTH, 2)); // 2 bytes for sc
399 }
400 
DoTargetTypeNdef(AppExecFwk::PacMap & pacMap)401 void TagHost::DoTargetTypeNdef(AppExecFwk::PacMap &pacMap)
402 {
403     DebugLog("DoTargetTypeNdef");
404     pacMap = ndefExtras_;
405     ndefExtras_.Clear();
406 }
407 
ParseTechExtras(uint32_t index)408 AppExecFwk::PacMap TagHost::ParseTechExtras(uint32_t index)
409 {
410     AppExecFwk::PacMap pacMap;
411     uint32_t targetType = static_cast<uint32_t>(tagTechList_[index]);
412     DebugLog("ParseTechExtras::targetType: %{public}d", targetType);
413     switch (targetType) {
414         case TagNciAdapterCommon::TARGET_TYPE_MIFARE_CLASSIC:
415             DoTargetTypeIso144433a(pacMap, index);
416             break;
417         case TagNciAdapterCommon::TARGET_TYPE_ISO14443_3A: {
418             DoTargetTypeIso144433a(pacMap, index);
419             break;
420         }
421         case TagNciAdapterCommon::TARGET_TYPE_ISO14443_3B: {
422             DoTargetTypeIso144433b(pacMap, index);
423             break;
424         }
425         case TagNciAdapterCommon::TARGET_TYPE_ISO14443_4: {
426             DoTargetTypeIso144434(pacMap, index);
427             break;
428         }
429         case TagNciAdapterCommon::TARGET_TYPE_V: {
430             DoTargetTypeV(pacMap, index);
431             break;
432         }
433         case TagNciAdapterCommon::TARGET_TYPE_MIFARE_UL: {
434             bool isUlC = IsUltralightC();
435             pacMap.PutBooleanValue(KITS::TagInfo::MIFARE_ULTRALIGHT_C_TYPE, isUlC);
436             DebugLog("ParseTechExtras::TARGET_TYPE_MIFARE_UL MIFARE_ULTRALIGHT_C_TYPE: %{public}d", isUlC);
437             break;
438         }
439         case TagNciAdapterCommon::TARGET_TYPE_FELICA: {
440             DoTargetTypeF(pacMap, index);
441             break;
442         }
443         case TagNciAdapterCommon::TARGET_TYPE_NDEF: {
444             DoTargetTypeNdef(pacMap);
445             break;
446         }
447         case TagNciAdapterCommon::TARGET_TYPE_NDEF_FORMATABLE:
448             break;
449         case TagNciAdapterCommon::TARGET_TYPE_UNKNOWN:
450             break;
451         default:
452             DebugLog("ParseTechExtras::unhandle for : %{public}d", targetType);
453             break;
454     }
455     return pacMap;
456 }
457 
GetTechExtrasData()458 std::vector<AppExecFwk::PacMap> TagHost::GetTechExtrasData()
459 {
460     DebugLog("TagHost::GetTechExtrasData, tech len.%{public}zu", tagTechList_.size());
461     tagTechExtras_.clear();
462     for (std::size_t i = 0; i < tagTechList_.size(); i++) {
463         AppExecFwk::PacMap extra = ParseTechExtras(i);
464         tagTechExtras_.push_back(extra);
465     }
466     return tagTechExtras_;
467 }
468 
GetTagRfDiscId()469 uint32_t TagHost::GetTagRfDiscId()
470 {
471     if (tagTechList_.size() > 0) {
472         return tagRfDiscIdList_[0];
473     }
474     return 0;
475 }
476 
SetNdefReadOnly()477 bool TagHost::SetNdefReadOnly()
478 {
479     DebugLog("TagHost::SetNdefReadOnly");
480     PauseFieldChecking();
481     std::lock_guard<std::mutex> lock(mutex_);
482     bool result = TagNciAdapterRw::GetInstance().SetReadOnly();
483     ResumeFieldChecking();
484     return result;
485 }
486 
ReadNdef()487 std::string TagHost::ReadNdef()
488 {
489     DebugLog("TagHost::ReadNdef");
490     PauseFieldChecking();
491     std::string response = "";
492     std::lock_guard<std::mutex> lock(mutex_);
493     TagNciAdapterRw::GetInstance().ReadNdef(response);
494     ResumeFieldChecking();
495     return response;
496 }
497 
FindNdefTech()498 std::string TagHost::FindNdefTech()
499 {
500     if (addNdefTech_) {
501         return "";
502     }
503     addNdefTech_ = true;
504     DebugLog("TagHost::FindNdefTech");
505     bool foundFormat = false;
506     uint32_t formatHandle = 0;
507     uint32_t formatLibNfcType = 0;
508     uint32_t index = tagTechList_.size();
509     std::string ndefMsg = "";
510     for (uint32_t i = 0; i < index; i++) {
511         for (uint32_t j = 0; j < i; j++) {
512             if (tagRfDiscIdList_[j] == tagRfDiscIdList_[i]) {
513                 continue;
514             }
515         }
516         if (!Connect(tagTechList_[i])) {
517             continue;
518         }
519         if (!foundFormat) {
520             if (TagNciAdapterRw::GetInstance().IsNdefFormattable()) { // no need to pause and resume
521                 formatHandle = tagRfDiscIdList_[i];
522                 formatLibNfcType = tagRfProtocols_[i];
523                 foundFormat = true;
524             }
525             Reconnect();
526         }
527         std::vector<int> ndefInfo;
528         if (TagNciAdapterRw::GetInstance().DetectNdefInfo(ndefInfo)) {
529             if (ndefInfo.size() < NDEF_INFO_SIZE) {
530                 WarnLog("TagHost::FindNdefTech, invalid size = %{public}zu", ndefInfo.size());
531                 return "";
532             }
533             DebugLog("Add ndef tag info, index: %{public}d", index);
534             // parse extras data for ndef tech.
535             AppExecFwk::PacMap pacMap;
536             ndefMsg = ReadNdef();
537             if (ndefMsg.size() > 0) {
538                 pacMap.PutStringValue(KITS::TagInfo::NDEF_MSG, ndefMsg);
539                 pacMap.PutIntValue(KITS::TagInfo::NDEF_FORUM_TYPE, GetNdefType(tagRfProtocols_[i]));
540                 DebugLog("ParseTechExtras::TARGET_TYPE_NDEF NDEF_FORUM_TYPE: %{public}d",
541                     GetNdefType(tagRfProtocols_[i]));
542                 pacMap.PutIntValue(KITS::TagInfo::NDEF_TAG_LENGTH, ndefInfo[NDEF_SIZE_INDEX]);
543                 pacMap.PutIntValue(KITS::TagInfo::NDEF_TAG_MODE, ndefInfo[NDEF_MODE_INDEX]);
544                 DebugLog("ParseTechExtras::TARGET_TYPE_NDEF NDEF_TAG_MODE: %{public}d", ndefInfo[1]);
545 
546                 AddNdefTechToTagInfo(TagNciAdapterCommon::TARGET_TYPE_NDEF, tagRfDiscIdList_[i],
547                     tagRfProtocols_[i], pacMap);
548                 foundFormat = false;
549                 Reconnect();
550             }
551             break;
552         }
553     }
554     if (foundFormat) {
555         DebugLog("Add ndef formatable tag info, index: %{public}d", index);
556         AppExecFwk::PacMap pacMap;
557         AddNdefTechToTagInfo(TagNciAdapterCommon::TARGET_TYPE_NDEF_FORMATABLE, formatHandle, formatLibNfcType, pacMap);
558     }
559     return ndefMsg;
560 }
561 
AddNdefTechToTagInfo(uint32_t tech,uint32_t discId,uint32_t actProto,AppExecFwk::PacMap pacMap)562 void TagHost::AddNdefTechToTagInfo(uint32_t tech, uint32_t discId, uint32_t actProto, AppExecFwk::PacMap pacMap)
563 {
564     InfoLog("AddNdefTechToTagInfo: tech = %{public}d", tech);
565     tagTechList_.push_back(tech);
566     tagRfDiscIdList_.push_back(discId);
567     tagRfProtocols_.push_back(actProto);
568     ndefExtras_ = pacMap; // techExtras_ will be handled in ParseTechExtras()
569 }
570 
GetNdefType(uint32_t protocol) const571 uint32_t TagHost::GetNdefType(uint32_t protocol) const
572 {
573     uint32_t ndefType;
574     if (NFA_PROTOCOL_T1T == protocol) {
575         ndefType = NDEF_TYPE1_TAG;
576     } else if (NFA_PROTOCOL_T2T == protocol) {
577         ndefType = NDEF_TYPE2_TAG;
578     } else if (NFA_PROTOCOL_T3T == protocol) {
579         ndefType = NDEF_TYPE3_TAG;
580     } else if (NFA_PROTOCOL_ISO_DEP == protocol) {
581         ndefType = NDEF_TYPE4_TAG;
582     } else if (NFC_PROTOCOL_MIFARE == protocol) {
583         ndefType = NDEF_MIFARE_CLASSIC_TAG;
584     } else {
585         /* NFA_PROTOCOL_T5T, NFA_PROTOCOL_INVALID and others */
586         ndefType = NDEF_UNKNOWN_TYPE;
587     }
588     return ndefType;
589 }
590 
WriteNdef(std::string & data)591 bool TagHost::WriteNdef(std::string& data)
592 {
593     DebugLog("TagHost::WriteNdef");
594     PauseFieldChecking();
595     std::lock_guard<std::mutex> lock(mutex_);
596     bool result = TagNciAdapterRw::GetInstance().WriteNdef(data);
597     ResumeFieldChecking();
598     DebugLog("TagHost::WriteNdef exit, result = %{public}d", result);
599     return result;
600 }
601 
FormatNdef(const std::string & key)602 bool TagHost::FormatNdef(const std::string& key)
603 {
604     DebugLog("TagHost::FormatNdef");
605     if (key.empty()) {
606         DebugLog("key is null");
607         return false;
608     }
609     PauseFieldChecking();
610     std::lock_guard<std::mutex> lock(mutex_);
611     bool result = TagNciAdapterRw::GetInstance().FormatNdef();
612     ResumeFieldChecking();
613     DebugLog("TagHost::FormatNdef exit, result = %{public}d", result);
614     return result;
615 }
616 
IsNdefFormatable()617 bool TagHost::IsNdefFormatable()
618 {
619     DebugLog("TagHost::IsNdefFormatable");
620     bool result = TagNciAdapterRw::GetInstance().IsNdefFormatable();
621     DebugLog("TagHost::IsNdefFormatable exit, result = %{public}d", result);
622     return result;
623 }
624 
DetectNdefInfo(std::vector<int> & ndefInfo)625 bool TagHost::DetectNdefInfo(std::vector<int>& ndefInfo)
626 {
627     DebugLog("TagHost::DetectNdefInfo");
628     PauseFieldChecking();
629     std::lock_guard<std::mutex> lock(mutex_);
630     bool result = TagNciAdapterRw::GetInstance().DetectNdefInfo(ndefInfo);
631     ResumeFieldChecking();
632     if (result) {
633         DebugLog("NDEF supported by the tag");
634     } else {
635         DebugLog("NDEF unsupported by the tag");
636     }
637     return result;
638 }
639 
GetConnectedTech()640 uint32_t TagHost::GetConnectedTech()
641 {
642     DebugLog("TagHost::GetConnectedTech");
643     if (connectedTechIndex_ != DEFAULT_VALUE) {
644         return tagTechList_[connectedTechIndex_];
645     }
646     return 0;
647 }
648 
IsUltralightC()649 bool TagHost::IsUltralightC()
650 {
651     PauseFieldChecking();
652     std::lock_guard<std::mutex> lock(mutex_);
653     bool result = false;
654 
655     // read the date content of speci addressed pages, see MIFARE Ultralight C
656     std::string command = "3002"; // 0x30 for mifare read, 0x02 for page address
657     std::string response;
658     TagNciAdapterRw::GetInstance().Transceive(command, response);
659     if (KITS::NfcSdkCommon::GetHexStrBytesLen(response) == NCI_MIFARE_ULTRALIGHT_C_RESPONSE_LENGTH) {
660         if (response[DATA_BYTE2] == NCI_MIFARE_ULTRALIGHT_C_BLANK_CARD &&
661             response[DATA_BYTE3] == NCI_MIFARE_ULTRALIGHT_C_BLANK_CARD &&
662             response[DATA_BYTE4] == NCI_MIFARE_ULTRALIGHT_C_BLANK_CARD &&
663             response[DATA_BYTE5] == NCI_MIFARE_ULTRALIGHT_C_BLANK_CARD &&
664             response[DATA_BYTE6] == NCI_MIFARE_ULTRALIGHT_C_BLANK_CARD &&
665             response[DATA_BYTE7] == NCI_MIFARE_ULTRALIGHT_C_BLANK_CARD &&
666             response[DATA_BYTE8] == NCI_MIFARE_ULTRALIGHT_C_VERSION_INFO_FIRST &&
667             response[DATA_BYTE9] == NCI_MIFARE_ULTRALIGHT_C_VERSION_INFO_SECOND) {
668             result = true;
669         } else if (response[DATA_BYTE4] == NCI_MIFARE_ULTRALIGHT_C_NDEF_CC &&
670                    ((response[DATA_BYTE5] & 0xff) < NCI_MIFARE_ULTRALIGHT_C_NDEF_MAJOR_VERSION) &&
671                    ((response[DATA_BYTE6] & 0xff) > NCI_MIFARE_ULTRALIGHT_C_NDEF_TAG_SIZE)) {
672             result = true;
673         }
674     }
675     ResumeFieldChecking();
676     return result;
677 }
678 }  // namespace NCI
679 }  // namespace NFC
680 }  // namespace OHOS
681