/* * Copyright 2022 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. */ #include "NfcDta.h" #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <cutils/properties.h> #include "SyncEvent.h" using android::base::StringPrintf; namespace android { extern SyncEvent gNfaSetConfigEvent; extern SyncEvent gNfaGetConfigEvent; extern uint16_t gCurrentConfigLen; extern uint8_t gConfig[256]; } // namespace android using namespace android; /******************************************************************************* ** ** Function: NfcDta ** ** Description: Initialize member variables. ** ** Returns: None ** *******************************************************************************/ NfcDta::NfcDta() { mDefaultTlv.clear(); mUpdatedParamIds.clear(); } /******************************************************************************* ** ** Function: getInstance ** ** Description: Get a reference to the singleton NfcDta object. ** ** Returns: Reference to NfcDta object. ** *******************************************************************************/ NfcDta& NfcDta::getInstance() { static NfcDta dtaInstance; return dtaInstance; } /******************************************************************************* ** ** Function: parseConfigParams ** ** Description: Parse config TLV from the String ** ** Returns: uint8_t vector ** *******************************************************************************/ std::vector<uint8_t> NfcDta::parseConfigParams(std::string configParams) { std::vector<uint8_t> configTlv; uint16_t index = 0; while (index < configParams.size()) { // Parsing tag configTlv.push_back( (uint8_t)strtol(configParams.substr(index, 2).c_str(), NULL, 16)); // Parsing length index += 2; uint16_t len = (uint8_t)strtol(configParams.substr(index, 2).c_str(), NULL, 16); configTlv.push_back(len); // Parsing value for (uint16_t i = 0; i < len; i++) { index += 2; configTlv.push_back( (uint8_t)strtol(configParams.substr(index, 2).c_str(), NULL, 16)); } index += 2; if (configParams[index] == '_') { index++; } } return configTlv; } /******************************************************************************* ** ** Function: getNonupdatedConfigParamIds ** ** Description: Get config parameter Ids whose values are not modified. ** ** Returns: config Parameter ids vector. ** *******************************************************************************/ std::vector<uint8_t> NfcDta::getNonupdatedConfigParamIds( std::vector<uint8_t> configTlv) { std::vector<uint8_t> paramIds; uint16_t index = 0; uint8_t len = 0; uint8_t paramId = 0; while (index < configTlv.size()) { paramId = configTlv[index++]; std::unordered_set<uint8_t>::const_iterator found = mUpdatedParamIds.find(paramId); if (found == mUpdatedParamIds.end()) { mUpdatedParamIds.insert(paramId); paramIds.push_back(paramId); } len = configTlv[index++]; index += len; } return paramIds; } /******************************************************************************* ** ** Function: getConfigParamValues ** ** Description: Read the current config parameter values. ** ** Returns: None. ** *******************************************************************************/ tNFA_STATUS NfcDta::getConfigParamValues(std::vector<uint8_t> paramIds) { tNFA_STATUS status = NFA_STATUS_OK; if (!paramIds.empty()) { SyncEventGuard guard(gNfaGetConfigEvent); status = NFA_GetConfig(paramIds.size(), paramIds.data()); if (status == NFA_STATUS_OK) { gNfaGetConfigEvent.wait(); // gCurrentConfigLen contains number of bytes without NCI header length. // i.e., status(one byte) + config tag count(one byte) + NCI config // Tag(one byte) + length(one byte) + value(bytes). So valid getConfig // response length should be greater than 4. if (gCurrentConfigLen > 4) { // Config tlv length = gCurrentConfigLen - status byte - tag count byte uint16_t len = gCurrentConfigLen - 2; // First Config TLV starts from index 1 of gConfig uint16_t index = 1; LOG(DEBUG) << StringPrintf("%s: default_config len: %d", __func__, len); while (index <= len) { mDefaultTlv.push_back(gConfig[index++]); } } else { LOG(DEBUG) << StringPrintf("%s: getConfig failed len: %d", __func__, gCurrentConfigLen); status = NFA_STATUS_FAILED; } } else { LOG(DEBUG) << StringPrintf("%s: getConfig failed", __func__); } } return status; } /******************************************************************************* ** ** Function: setConfigParams ** ** Description: Set config param with new value. ** ** Returns: NFA_STATUS_OK if success ** *******************************************************************************/ tNFA_STATUS NfcDta::setConfigParams(std::vector<uint8_t> configTlv) { tNFA_STATUS status = NFA_STATUS_FAILED; uint16_t index = 0; uint8_t paramId = 0; uint8_t len = 0; while (index < configTlv.size()) { paramId = configTlv[index++]; len = configTlv[index++]; LOG(DEBUG) << StringPrintf("%s: Param Id: %02X, Length: %02X", __func__, paramId, len); SyncEventGuard guard(gNfaSetConfigEvent); status = NFA_SetConfig(paramId, len, &configTlv[index]); if (status == NFA_STATUS_OK) { gNfaSetConfigEvent.wait(); } else { LOG(DEBUG) << StringPrintf("%s: setConfig failed", __func__); break; } index += len; } return status; } /******************************************************************************* ** ** Function: setNfccConfigParams ** ** Description: Set NCI config params from nfc.configTLV System Property. ** ** Returns: None. ** *******************************************************************************/ void NfcDta::setNfccConfigParams() { char sysPropTlvs[256]; int len = 0; len = property_get("nfc.dta.configTLV", sysPropTlvs, ""); std::string configTlvs(sysPropTlvs); LOG(DEBUG) << StringPrintf("%s: SysProperty nfc.configTLV: %s", __func__, configTlvs.c_str()); if (len <= 0 || (configTlvs.empty() && mDefaultTlv.empty())) { LOG(DEBUG) << StringPrintf("%s: Config TLVs not available", __func__); return; } tNFA_STATUS status = NFA_STATUS_FAILED; if (configTlvs.empty() && !mDefaultTlv.empty()) { status = setConfigParams(mDefaultTlv); if (status == NFA_STATUS_OK) { mDefaultTlv.clear(); mUpdatedParamIds.clear(); LOG(DEBUG) << StringPrintf("%s: Restored default config params", __func__); } return; } std::vector<uint8_t> tlv = parseConfigParams(configTlvs); std::vector<uint8_t> paramIds = getNonupdatedConfigParamIds(tlv); status = getConfigParamValues(paramIds); if (status == NFA_STATUS_OK) { setConfigParams(tlv); } LOG(DEBUG) << StringPrintf("%s: Exit", __func__); }