aboutsummaryrefslogtreecommitdiff
path: root/pn54x/utils
diff options
context:
space:
mode:
Diffstat (limited to 'pn54x/utils')
-rw-r--r--pn54x/utils/phNxpConfig.cpp865
-rw-r--r--pn54x/utils/phNxpConfig.h100
-rw-r--r--pn54x/utils/phNxpNciHal_utils.c477
-rw-r--r--pn54x/utils/phNxpNciHal_utils.h106
-rw-r--r--pn54x/utils/sparse_crc32.c107
-rw-r--r--pn54x/utils/sparse_crc32.h32
6 files changed, 1687 insertions, 0 deletions
diff --git a/pn54x/utils/phNxpConfig.cpp b/pn54x/utils/phNxpConfig.cpp
new file mode 100644
index 0000000..9e8c7cb
--- /dev/null
+++ b/pn54x/utils/phNxpConfig.cpp
@@ -0,0 +1,865 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * The original Work has been changed by NXP Semiconductors.
+ *
+ * Copyright (C) 2013-2014 NXP Semiconductors
+ *
+ * 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 <stdio.h>
+#include <sys/stat.h>
+#include <list>
+#include <string>
+#include <vector>
+
+#include <phNxpConfig.h>
+#include <phNxpLog.h>
+#include "sparse_crc32.h"
+
+#if GENERIC_TARGET
+const char alternative_config_path[] = "/data/vendor/nfc/";
+#else
+const char alternative_config_path[] = "";
+#endif
+
+#if 1
+const char* transport_config_paths[] = {"/odm/etc/", "/vendor/etc/", "/etc/"};
+#else
+const char* transport_config_paths[] = {"res/"};
+#endif
+const int transport_config_path_size =
+ (sizeof(transport_config_paths) / sizeof(transport_config_paths[0]));
+
+#define config_name "libnfc-nxp.conf"
+#define extra_config_base "libnfc-nxp-"
+#define extra_config_ext ".conf"
+#define IsStringValue 0x80000000
+
+const char config_timestamp_path[] =
+ "/data/vendor/nfc/libnfc-nxpConfigState.bin";
+
+namespace {
+
+size_t readConfigFile(const char* fileName, uint8_t** p_data) {
+ FILE* fd = fopen(fileName, "rb");
+ if (fd == nullptr) return 0;
+
+ fseek(fd, 0L, SEEK_END);
+ const size_t file_size = ftell(fd);
+ rewind(fd);
+
+ uint8_t* buffer = new uint8_t[file_size];
+ size_t read = fread(buffer, file_size, 1, fd);
+ fclose(fd);
+
+ if (read == 1) {
+ *p_data = buffer;
+ return file_size;
+ }
+
+ return 0;
+}
+
+} // namespace
+
+using namespace ::std;
+
+class CNfcParam : public string {
+ public:
+ CNfcParam();
+ CNfcParam(const char* name, const string& value);
+ CNfcParam(const char* name, unsigned long value);
+ virtual ~CNfcParam();
+ unsigned long numValue() const { return m_numValue; }
+ const char* str_value() const { return m_str_value.c_str(); }
+ size_t str_len() const { return m_str_value.length(); }
+
+ private:
+ string m_str_value;
+ unsigned long m_numValue;
+};
+
+class CNfcConfig : public vector<const CNfcParam*> {
+ public:
+ virtual ~CNfcConfig();
+ static CNfcConfig& GetInstance();
+ friend void readOptionalConfig(const char* optional);
+ bool isModified();
+ void resetModified();
+
+ bool getValue(const char* name, char* pValue, size_t len) const;
+ bool getValue(const char* name, unsigned long& rValue) const;
+ bool getValue(const char* name, unsigned short& rValue) const;
+ bool getValue(const char* name, char* pValue, long len, long* readlen) const;
+ const CNfcParam* find(const char* p_name) const;
+ void clean();
+
+ private:
+ CNfcConfig();
+ bool readConfig(const char* name, bool bResetContent);
+ void moveFromList();
+ void moveToList();
+ void add(const CNfcParam* pParam);
+ list<const CNfcParam*> m_list;
+ bool mValidFile;
+ uint32_t config_crc32_;
+
+ unsigned long state;
+
+ inline bool Is(unsigned long f) { return (state & f) == f; }
+ inline void Set(unsigned long f) { state |= f; }
+ inline void Reset(unsigned long f) { state &= ~f; }
+};
+
+/*******************************************************************************
+**
+** Function: isPrintable()
+**
+** Description: determine if 'c' is printable
+**
+** Returns: 1, if printable, otherwise 0
+**
+*******************************************************************************/
+inline bool isPrintable(char c) {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') || c == '/' || c == '_' || c == '-' || c == '.';
+}
+
+/*******************************************************************************
+**
+** Function: isDigit()
+**
+** Description: determine if 'c' is numeral digit
+**
+** Returns: true, if numerical digit
+**
+*******************************************************************************/
+inline bool isDigit(char c, int base) {
+ if ('0' <= c && c <= '9') return true;
+ if (base == 16) {
+ if (('A' <= c && c <= 'F') || ('a' <= c && c <= 'f')) return true;
+ }
+ return false;
+}
+
+/*******************************************************************************
+**
+** Function: getDigitValue()
+**
+** Description: return numerical value of a decimal or hex char
+**
+** Returns: numerical value if decimal or hex char, otherwise 0
+**
+*******************************************************************************/
+inline int getDigitValue(char c, int base) {
+ if ('0' <= c && c <= '9') return c - '0';
+ if (base == 16) {
+ if ('A' <= c && c <= 'F')
+ return c - 'A' + 10;
+ else if ('a' <= c && c <= 'f')
+ return c - 'a' + 10;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function: findConfigFilePathFromTransportConfigPaths()
+**
+** Description: find a config file path with a given config name from transport
+** config paths
+**
+** Returns: none
+**
+*******************************************************************************/
+void findConfigFilePathFromTransportConfigPaths(const string& configName,
+ string& filePath) {
+ for (int i = 0; i < transport_config_path_size - 1; i++) {
+ filePath.assign(transport_config_paths[i]);
+ filePath += configName;
+ struct stat file_stat;
+ if (stat(filePath.c_str(), &file_stat) == 0 && S_ISREG(file_stat.st_mode)) {
+ return;
+ }
+ }
+ filePath.assign(transport_config_paths[transport_config_path_size - 1]);
+ filePath += configName;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::readConfig()
+**
+** Description: read Config settings and parse them into a linked list
+** move the element from linked list to a array at the end
+**
+** Returns: 1, if there are any config data, 0 otherwise
+**
+*******************************************************************************/
+bool CNfcConfig::readConfig(const char* name, bool bResetContent) {
+ enum {
+ BEGIN_LINE = 1,
+ TOKEN,
+ STR_VALUE,
+ NUM_VALUE,
+ BEGIN_HEX,
+ BEGIN_QUOTE,
+ END_LINE
+ };
+
+ uint8_t* p_config = nullptr;
+ size_t config_size = readConfigFile(name, &p_config);
+ if (p_config == nullptr) {
+ ALOGE("%s Cannot open config file %s\n", __func__, name);
+ if (bResetContent) {
+ ALOGE("%s Using default value for all settings\n", __func__);
+ mValidFile = false;
+ }
+ return false;
+ }
+
+ string token;
+ string strValue;
+ unsigned long numValue = 0;
+ CNfcParam* pParam = NULL;
+ int i = 0;
+ int base = 0;
+ char c;
+ int bflag = 0;
+ state = BEGIN_LINE;
+
+ config_crc32_ = sparse_crc32(0, p_config, config_size);
+ mValidFile = true;
+ if (size() > 0) {
+ if (bResetContent)
+ clean();
+ else
+ moveToList();
+ }
+
+ for (size_t offset = 0; offset != config_size; ++offset) {
+ c = p_config[offset];
+ switch (state & 0xff) {
+ case BEGIN_LINE:
+ if (c == '#')
+ state = END_LINE;
+ else if (isPrintable(c)) {
+ i = 0;
+ token.erase();
+ strValue.erase();
+ state = TOKEN;
+ token.push_back(c);
+ }
+ break;
+ case TOKEN:
+ if (c == '=') {
+ token.push_back('\0');
+ state = BEGIN_QUOTE;
+ } else if (isPrintable(c))
+ token.push_back(c);
+ else
+ state = END_LINE;
+ break;
+ case BEGIN_QUOTE:
+ if (c == '"') {
+ state = STR_VALUE;
+ base = 0;
+ } else if (c == '0')
+ state = BEGIN_HEX;
+ else if (isDigit(c, 10)) {
+ state = NUM_VALUE;
+ base = 10;
+ numValue = getDigitValue(c, base);
+ i = 0;
+ } else if (c == '{') {
+ state = NUM_VALUE;
+ bflag = 1;
+ base = 16;
+ i = 0;
+ Set(IsStringValue);
+ } else
+ state = END_LINE;
+ break;
+ case BEGIN_HEX:
+ if (c == 'x' || c == 'X') {
+ state = NUM_VALUE;
+ base = 16;
+ numValue = 0;
+ i = 0;
+ break;
+ } else if (isDigit(c, 10)) {
+ state = NUM_VALUE;
+ base = 10;
+ numValue = getDigitValue(c, base);
+ break;
+ } else if (c != '\n' && c != '\r') {
+ state = END_LINE;
+ break;
+ }
+ // fall through to numValue to handle numValue
+
+ case NUM_VALUE:
+ if (isDigit(c, base)) {
+ numValue *= base;
+ numValue += getDigitValue(c, base);
+ ++i;
+ } else if (bflag == 1 &&
+ (c == ' ' || c == '\r' || c == '\n' || c == '\t')) {
+ break;
+ } else if (base == 16 &&
+ (c == ',' || c == ':' || c == '-' || c == ' ' || c == '}')) {
+ if (c == '}') {
+ bflag = 0;
+ }
+ if (i > 0) {
+ int n = (i + 1) / 2;
+ while (n-- > 0) {
+ numValue = numValue >> (n * 8);
+ unsigned char c = (numValue)&0xFF;
+ strValue.push_back(c);
+ }
+ }
+
+ Set(IsStringValue);
+ numValue = 0;
+ i = 0;
+ } else {
+ if (c == '\n' || c == '\r') {
+ if (bflag == 0) {
+ state = BEGIN_LINE;
+ }
+ } else {
+ if (bflag == 0) {
+ state = END_LINE;
+ }
+ }
+ if (Is(IsStringValue) && base == 16 && i > 0) {
+ int n = (i + 1) / 2;
+ while (n-- > 0) strValue.push_back(((numValue >> (n * 8)) & 0xFF));
+ }
+ if (strValue.length() > 0)
+ pParam = new CNfcParam(token.c_str(), strValue);
+ else
+ pParam = new CNfcParam(token.c_str(), numValue);
+ add(pParam);
+ strValue.erase();
+ numValue = 0;
+ }
+ break;
+ case STR_VALUE:
+ if (c == '"') {
+ strValue.push_back('\0');
+ state = END_LINE;
+ pParam = new CNfcParam(token.c_str(), strValue);
+ add(pParam);
+ } else if (isPrintable(c))
+ strValue.push_back(c);
+ break;
+ case END_LINE:
+ if (c == '\n' || c == '\r') state = BEGIN_LINE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ delete[] p_config;
+
+ moveFromList();
+ return size() > 0;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::CNfcConfig()
+**
+** Description: class constructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcConfig::CNfcConfig() : mValidFile(true), state(0) {}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::~CNfcConfig()
+**
+** Description: class destructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcConfig::~CNfcConfig() {}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::GetInstance()
+**
+** Description: get class singleton object
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcConfig& CNfcConfig::GetInstance() {
+ static CNfcConfig theInstance;
+
+ if (theInstance.size() == 0 && theInstance.mValidFile) {
+ string strPath;
+ if (alternative_config_path[0] != '\0') {
+ strPath.assign(alternative_config_path);
+ strPath += config_name;
+ theInstance.readConfig(strPath.c_str(), true);
+ if (!theInstance.empty()) {
+ return theInstance;
+ }
+ }
+ findConfigFilePathFromTransportConfigPaths(config_name, strPath);
+ theInstance.readConfig(strPath.c_str(), true);
+ }
+
+ return theInstance;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::getValue()
+**
+** Description: get a string value of a setting
+**
+** Returns: true if setting exists
+** false if setting does not exist
+**
+*******************************************************************************/
+bool CNfcConfig::getValue(const char* name, char* pValue, size_t len) const {
+ const CNfcParam* pParam = find(name);
+ if (pParam == NULL) return false;
+
+ if (pParam->str_len() > 0) {
+ memset(pValue, 0, len);
+ memcpy(pValue, pParam->str_value(), pParam->str_len());
+ return true;
+ }
+ return false;
+}
+
+bool CNfcConfig::getValue(const char* name, char* pValue, long len,
+ long* readlen) const {
+ const CNfcParam* pParam = find(name);
+ if (pParam == NULL) return false;
+
+ if (pParam->str_len() > 0) {
+ if (pParam->str_len() <= (unsigned long)len) {
+ memset(pValue, 0, len);
+ memcpy(pValue, pParam->str_value(), pParam->str_len());
+ *readlen = pParam->str_len();
+ } else {
+ *readlen = -1;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::getValue()
+**
+** Description: get a long numerical value of a setting
+**
+** Returns: true if setting exists
+** false if setting does not exist
+**
+*******************************************************************************/
+bool CNfcConfig::getValue(const char* name, unsigned long& rValue) const {
+ const CNfcParam* pParam = find(name);
+ if (pParam == NULL) return false;
+
+ if (pParam->str_len() == 0) {
+ rValue = static_cast<unsigned long>(pParam->numValue());
+ return true;
+ }
+ return false;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::getValue()
+**
+** Description: get a short numerical value of a setting
+**
+** Returns: true if setting exists
+** false if setting does not exist
+**
+*******************************************************************************/
+bool CNfcConfig::getValue(const char* name, unsigned short& rValue) const {
+ const CNfcParam* pParam = find(name);
+ if (pParam == NULL) return false;
+
+ if (pParam->str_len() == 0) {
+ rValue = static_cast<unsigned short>(pParam->numValue());
+ return true;
+ }
+ return false;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::find()
+**
+** Description: search if a setting exist in the setting array
+**
+** Returns: pointer to the setting object
+**
+*******************************************************************************/
+const CNfcParam* CNfcConfig::find(const char* p_name) const {
+ if (size() == 0) return NULL;
+
+ for (const_iterator it = begin(), itEnd = end(); it != itEnd; ++it) {
+ if (**it < p_name) {
+ continue;
+ } else if (**it == p_name) {
+ if ((*it)->str_len() > 0) {
+ NXPLOG_EXTNS_D("%s found %s=%s\n", __func__, p_name,
+ (*it)->str_value());
+ } else {
+ NXPLOG_EXTNS_D("%s found %s=(0x%lx)\n", __func__, p_name,
+ (*it)->numValue());
+ }
+ return *it;
+ } else
+ break;
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::clean()
+**
+** Description: reset the setting array
+**
+** Returns: none
+**
+*******************************************************************************/
+void CNfcConfig::clean() {
+ if (size() == 0) return;
+
+ for (iterator it = begin(), itEnd = end(); it != itEnd; ++it) delete *it;
+ clear();
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::Add()
+**
+** Description: add a setting object to the list
+**
+** Returns: none
+**
+*******************************************************************************/
+void CNfcConfig::add(const CNfcParam* pParam) {
+ if (m_list.size() == 0) {
+ m_list.push_back(pParam);
+ return;
+ }
+ for (list<const CNfcParam *>::iterator it = m_list.begin(),
+ itEnd = m_list.end();
+ it != itEnd; ++it) {
+ if (**it < pParam->c_str()) continue;
+ m_list.insert(it, pParam);
+ return;
+ }
+ m_list.push_back(pParam);
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::moveFromList()
+**
+** Description: move the setting object from list to array
+**
+** Returns: none
+**
+*******************************************************************************/
+void CNfcConfig::moveFromList() {
+ if (m_list.size() == 0) return;
+
+ for (list<const CNfcParam *>::iterator it = m_list.begin(),
+ itEnd = m_list.end();
+ it != itEnd; ++it)
+ push_back(*it);
+ m_list.clear();
+}
+
+/*******************************************************************************
+**
+** Function: CNfcConfig::moveToList()
+**
+** Description: move the setting object from array to list
+**
+** Returns: none
+**
+*******************************************************************************/
+void CNfcConfig::moveToList() {
+ if (m_list.size() != 0) m_list.clear();
+
+ for (iterator it = begin(), itEnd = end(); it != itEnd; ++it)
+ m_list.push_back(*it);
+ clear();
+}
+
+bool CNfcConfig::isModified() {
+ FILE* fd = fopen(config_timestamp_path, "r+");
+ if (fd == nullptr) {
+ ALOGE("%s Unable to open file '%s' - assuming modified", __func__,
+ config_timestamp_path);
+ return true;
+ }
+
+ uint32_t stored_crc32 = 0;
+ fread(&stored_crc32, sizeof(uint32_t), 1, fd);
+ fclose(fd);
+
+ return stored_crc32 != config_crc32_;
+}
+
+void CNfcConfig::resetModified() {
+ FILE* fd = fopen(config_timestamp_path, "w+");
+ if (fd == nullptr) {
+ ALOGE("%s Unable to open file '%s' for writing", __func__,
+ config_timestamp_path);
+ return;
+ }
+
+ fwrite(&config_crc32_, sizeof(uint32_t), 1, fd);
+ fclose(fd);
+}
+
+/*******************************************************************************
+**
+** Function: CNfcParam::CNfcParam()
+**
+** Description: class constructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcParam::CNfcParam() : m_numValue(0) {}
+
+/*******************************************************************************
+**
+** Function: CNfcParam::~CNfcParam()
+**
+** Description: class destructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcParam::~CNfcParam() {}
+
+/*******************************************************************************
+**
+** Function: CNfcParam::CNfcParam()
+**
+** Description: class copy constructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcParam::CNfcParam(const char* name, const string& value)
+ : string(name), m_str_value(value), m_numValue(0) {}
+
+/*******************************************************************************
+**
+** Function: CNfcParam::CNfcParam()
+**
+** Description: class copy constructor
+**
+** Returns: none
+**
+*******************************************************************************/
+CNfcParam::CNfcParam(const char* name, unsigned long value)
+ : string(name), m_numValue(value) {}
+
+/*******************************************************************************
+**
+** Function: GetStrValue
+**
+** Description: API function for getting a string value of a setting
+**
+** Returns: True if found, otherwise False.
+**
+*******************************************************************************/
+extern "C" int GetNxpStrValue(const char* name, char* pValue,
+ unsigned long len) {
+ CNfcConfig& rConfig = CNfcConfig::GetInstance();
+
+ return rConfig.getValue(name, pValue, len);
+}
+
+/*******************************************************************************
+**
+** Function: GetByteArrayValue()
+**
+** Description: Read byte array value from the config file.
+**
+** Parameters:
+** name - name of the config param to read.
+** pValue - pointer to input buffer.
+** bufflen - input buffer length.
+** len - out parameter to return the number of bytes read from
+** config file, return -1 in case bufflen is not enough.
+**
+** Returns: TRUE[1] if config param name is found in the config file, else
+** FALSE[0]
+**
+*******************************************************************************/
+extern "C" int GetNxpByteArrayValue(const char* name, char* pValue,
+ long bufflen, long* len) {
+ CNfcConfig& rConfig = CNfcConfig::GetInstance();
+
+ return rConfig.getValue(name, pValue, bufflen, len);
+}
+
+/*******************************************************************************
+**
+** Function: GetNumValue
+**
+** Description: API function for getting a numerical value of a setting
+**
+** Returns: true, if successful
+**
+*******************************************************************************/
+extern "C" int GetNxpNumValue(const char* name, void* pValue,
+ unsigned long len) {
+ if (!pValue) return false;
+
+ CNfcConfig& rConfig = CNfcConfig::GetInstance();
+ const CNfcParam* pParam = rConfig.find(name);
+
+ if (pParam == NULL) return false;
+ unsigned long v = pParam->numValue();
+ if (v == 0 && pParam->str_len() > 0 && pParam->str_len() < 4) {
+ const unsigned char* p = (const unsigned char*)pParam->str_value();
+ for (unsigned int i = 0; i < pParam->str_len(); ++i) {
+ v *= 256;
+ v += *p++;
+ }
+ }
+ switch (len) {
+ case sizeof(unsigned long):
+ *(static_cast<unsigned long*>(pValue)) = (unsigned long)v;
+ break;
+ case sizeof(unsigned short):
+ *(static_cast<unsigned short*>(pValue)) = (unsigned short)v;
+ break;
+ case sizeof(unsigned char):
+ *(static_cast<unsigned char*>(pValue)) = (unsigned char)v;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+/*******************************************************************************
+**
+** Function: resetConfig
+**
+** Description: reset settings array
+**
+** Returns: none
+**
+*******************************************************************************/
+extern "C" void resetNxpConfig()
+
+{
+ CNfcConfig& rConfig = CNfcConfig::GetInstance();
+
+ rConfig.clean();
+}
+
+/*******************************************************************************
+**
+** Function: readOptionalConfig()
+**
+** Description: read Config settings from an optional conf file
+**
+** Returns: none
+**
+*******************************************************************************/
+void readOptionalConfig(const char* extra) {
+ string strPath;
+ string configName(extra_config_base);
+ configName += extra;
+ configName += extra_config_ext;
+
+ if (alternative_config_path[0] != '\0') {
+ strPath.assign(alternative_config_path);
+ strPath += configName;
+ } else {
+ findConfigFilePathFromTransportConfigPaths(configName, strPath);
+ }
+
+ CNfcConfig::GetInstance().readConfig(strPath.c_str(), false);
+}
+
+/*******************************************************************************
+**
+** Function: isNxpConfigModified()
+**
+** Description: check if config file has modified
+**
+** Returns: 0 if not modified, 1 otherwise.
+**
+*******************************************************************************/
+extern "C" int isNxpConfigModified() {
+ CNfcConfig& rConfig = CNfcConfig::GetInstance();
+ return rConfig.isModified();
+}
+
+/*******************************************************************************
+**
+** Function: updateNxpConfigTimestamp()
+**
+** Description: update if config file has modified
+**
+** Returns: 0 if not modified, 1 otherwise.
+**
+*******************************************************************************/
+extern "C" int updateNxpConfigTimestamp() {
+ CNfcConfig& rConfig = CNfcConfig::GetInstance();
+ rConfig.resetModified();
+ return 0;
+}
diff --git a/pn54x/utils/phNxpConfig.h b/pn54x/utils/phNxpConfig.h
new file mode 100644
index 0000000..9488ecc
--- /dev/null
+++ b/pn54x/utils/phNxpConfig.h
@@ -0,0 +1,100 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * The original Work has been changed by NXP Semiconductors.
+ *
+ * Copyright (C) 2013-2014 NXP Semiconductors
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int GetNxpStrValue(const char* name, char* p_value, unsigned long len);
+int GetNxpNumValue(const char* name, void* p_value, unsigned long len);
+int GetNxpByteArrayValue(const char* name, char* pValue, long bufflen,
+ long* len);
+void resetNxpConfig(void);
+int isNxpConfigModified();
+int updateNxpConfigTimestamp();
+
+#ifdef __cplusplus
+};
+#endif
+
+#define NAME_NXPLOG_EXTNS_LOGLEVEL "NXPLOG_EXTNS_LOGLEVEL"
+#define NAME_NXPLOG_NCIHAL_LOGLEVEL "NXPLOG_NCIHAL_LOGLEVEL"
+#define NAME_NXPLOG_NCIX_LOGLEVEL "NXPLOG_NCIX_LOGLEVEL"
+#define NAME_NXPLOG_NCIR_LOGLEVEL "NXPLOG_NCIR_LOGLEVEL"
+#define NAME_NXPLOG_FWDNLD_LOGLEVEL "NXPLOG_FWDNLD_LOGLEVEL"
+#define NAME_NXPLOG_TML_LOGLEVEL "NXPLOG_TML_LOGLEVEL"
+
+#define NAME_MIFARE_READER_ENABLE "MIFARE_READER_ENABLE"
+#define NAME_FW_STORAGE "FW_STORAGE"
+#define NAME_NXP_NFC_DEV_NODE "NXP_NFC_DEV_NODE"
+#define NAME_NXP_FW_NAME "NXP_FW_NAME"
+#define NAME_NXP_FW_PROTECION_OVERRIDE "NXP_FW_PROTECION_OVERRIDE"
+#define NAME_NXP_SYS_CLK_SRC_SEL "NXP_SYS_CLK_SRC_SEL"
+#define NAME_NXP_SYS_CLK_FREQ_SEL "NXP_SYS_CLK_FREQ_SEL"
+#define NAME_NXP_SYS_CLOCK_TO_CFG "NXP_SYS_CLOCK_TO_CFG"
+#define NAME_NXP_ACT_PROP_EXTN "NXP_ACT_PROP_EXTN"
+#define NAME_NXP_EXT_TVDD_CFG "NXP_EXT_TVDD_CFG"
+#define NAME_NXP_EXT_TVDD_CFG_1 "NXP_EXT_TVDD_CFG_1"
+#define NAME_NXP_EXT_TVDD_CFG_2 "NXP_EXT_TVDD_CFG_2"
+#define NAME_NXP_EXT_TVDD_CFG_3 "NXP_EXT_TVDD_CFG_3"
+#define NAME_NXP_RF_CONF_BLK_1 "NXP_RF_CONF_BLK_1"
+#define NAME_NXP_RF_CONF_BLK_2 "NXP_RF_CONF_BLK_2"
+#define NAME_NXP_RF_CONF_BLK_3 "NXP_RF_CONF_BLK_3"
+#define NAME_NXP_RF_CONF_BLK_4 "NXP_RF_CONF_BLK_4"
+#define NAME_NXP_RF_CONF_BLK_5 "NXP_RF_CONF_BLK_5"
+#define NAME_NXP_RF_CONF_BLK_6 "NXP_RF_CONF_BLK_6"
+#define NAME_NXP_CORE_CONF_EXTN "NXP_CORE_CONF_EXTN"
+#define NAME_NXP_CORE_CONF "NXP_CORE_CONF"
+#define NAME_NXP_CORE_MFCKEY_SETTING "NXP_CORE_MFCKEY_SETTING"
+#define NAME_NXP_CORE_STANDBY "NXP_CORE_STANDBY"
+#define NAME_NXP_NFC_PROFILE_EXTN "NXP_NFC_PROFILE_EXTN"
+#define NAME_NXP_CHINA_TIANJIN_RF_ENABLED "NXP_CHINA_TIANJIN_RF_ENABLED"
+#define NAME_NXP_SWP_SWITCH_TIMEOUT "NXP_SWP_SWITCH_TIMEOUT"
+#define NAME_NXP_SWP_FULL_PWR_ON "NXP_SWP_FULL_PWR_ON"
+#define NAME_NXP_CORE_RF_FIELD "NXP_CORE_RF_FIELD"
+#define NAME_NXP_NFC_MERGE_RF_PARAMS "NXP_NFC_MERGE_RF_PARAMS"
+#define NAME_NXP_I2C_FRAGMENTATION_ENABLED "NXP_I2C_FRAGMENTATION_ENABLED"
+#define NAME_AID_MATCHING_PLATFORM "AID_MATCHING_PLATFORM"
+
+/* default configuration */
+#define default_storage_location "/data/vendor/nfc"
+
+#endif
diff --git a/pn54x/utils/phNxpNciHal_utils.c b/pn54x/utils/phNxpNciHal_utils.c
new file mode 100644
index 0000000..46e4908
--- /dev/null
+++ b/pn54x/utils/phNxpNciHal_utils.c
@@ -0,0 +1,477 @@
+/*
+ *
+ * Copyright (C) 2013-2014 NXP Semiconductors
+ *
+ * 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 <errno.h>
+#include <pthread.h>
+
+#include <phNxpLog.h>
+#include <phNxpNciHal.h>
+#include <phNxpNciHal_utils.h>
+
+#if (NFC_NXP_CHIP_TYPE == PN548C2)
+extern uint8_t discovery_cmd[50];
+extern uint8_t discovery_cmd_len;
+extern uint8_t nfcdep_detected;
+#endif
+
+/*********************** Link list functions **********************************/
+
+/*******************************************************************************
+**
+** Function listInit
+**
+** Description List initialization
+**
+** Returns 1, if list initialized, 0 otherwise
+**
+*******************************************************************************/
+int listInit(struct listHead* pList) {
+ pList->pFirst = NULL;
+ if (pthread_mutex_init(&pList->mutex, NULL) == -1) {
+ NXPLOG_NCIHAL_E("Mutex creation failed (errno=0x%08x)", errno);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*******************************************************************************
+**
+** Function listDestroy
+**
+** Description List destruction
+**
+** Returns 1, if list destroyed, 0 if failed
+**
+*******************************************************************************/
+int listDestroy(struct listHead* pList) {
+ int bListNotEmpty = 1;
+ while (bListNotEmpty) {
+ bListNotEmpty = listGetAndRemoveNext(pList, NULL);
+ }
+
+ if (pthread_mutex_destroy(&pList->mutex) == -1) {
+ NXPLOG_NCIHAL_E("Mutex destruction failed (errno=0x%08x)", errno);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*******************************************************************************
+**
+** Function listAdd
+**
+** Description Add a node to the list
+**
+** Returns 1, if added, 0 if otherwise
+**
+*******************************************************************************/
+int listAdd(struct listHead* pList, void* pData) {
+ struct listNode* pNode;
+ struct listNode* pLastNode;
+ int result;
+
+ /* Create node */
+ pNode = (struct listNode*)malloc(sizeof(struct listNode));
+ if (pNode == NULL) {
+ result = 0;
+ NXPLOG_NCIHAL_E("Failed to malloc");
+ goto clean_and_return;
+ }
+ pNode->pData = pData;
+ pNode->pNext = NULL;
+
+ pthread_mutex_lock(&pList->mutex);
+
+ /* Add the node to the list */
+ if (pList->pFirst == NULL) {
+ /* Set the node as the head */
+ pList->pFirst = pNode;
+ } else {
+ /* Seek to the end of the list */
+ pLastNode = pList->pFirst;
+ while (pLastNode->pNext != NULL) {
+ pLastNode = pLastNode->pNext;
+ }
+
+ /* Add the node to the current list */
+ pLastNode->pNext = pNode;
+ }
+
+ result = 1;
+
+clean_and_return:
+ pthread_mutex_unlock(&pList->mutex);
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function listRemove
+**
+** Description Remove node from the list
+**
+** Returns 1, if removed, 0 if otherwise
+**
+*******************************************************************************/
+int listRemove(struct listHead* pList, void* pData) {
+ struct listNode* pNode;
+ struct listNode* pRemovedNode;
+ int result;
+
+ pthread_mutex_lock(&pList->mutex);
+
+ if (pList->pFirst == NULL) {
+ /* Empty list */
+ NXPLOG_NCIHAL_E("Failed to deallocate (list empty)");
+ result = 0;
+ goto clean_and_return;
+ }
+
+ pNode = pList->pFirst;
+ if (pList->pFirst->pData == pData) {
+ /* Get the removed node */
+ pRemovedNode = pNode;
+
+ /* Remove the first node */
+ pList->pFirst = pList->pFirst->pNext;
+ } else {
+ while (pNode->pNext != NULL) {
+ if (pNode->pNext->pData == pData) {
+ /* Node found ! */
+ break;
+ }
+ pNode = pNode->pNext;
+ }
+
+ if (pNode->pNext == NULL) {
+ /* Node not found */
+ result = 0;
+ NXPLOG_NCIHAL_E("Failed to deallocate (not found %8p)", pData);
+ goto clean_and_return;
+ }
+
+ /* Get the removed node */
+ pRemovedNode = pNode->pNext;
+
+ /* Remove the node from the list */
+ pNode->pNext = pNode->pNext->pNext;
+ }
+
+ /* Deallocate the node */
+ free(pRemovedNode);
+
+ result = 1;
+
+clean_and_return:
+ pthread_mutex_unlock(&pList->mutex);
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function listGetAndRemoveNext
+**
+** Description Get next node on the list and remove it
+**
+** Returns 1, if successful, 0 if otherwise
+**
+*******************************************************************************/
+int listGetAndRemoveNext(struct listHead* pList, void** ppData) {
+ struct listNode* pNode;
+ int result;
+
+ pthread_mutex_lock(&pList->mutex);
+
+ if (pList->pFirst == NULL) {
+ /* Empty list */
+ NXPLOG_NCIHAL_D("Failed to deallocate (list empty)");
+ result = 0;
+ goto clean_and_return;
+ }
+
+ /* Work on the first node */
+ pNode = pList->pFirst;
+
+ /* Return the data */
+ if (ppData != NULL) {
+ *ppData = pNode->pData;
+ }
+
+ /* Remove and deallocate the node */
+ pList->pFirst = pNode->pNext;
+ free(pNode);
+
+ result = 1;
+
+clean_and_return:
+ listDump(pList);
+ pthread_mutex_unlock(&pList->mutex);
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function listDump
+**
+** Description Dump list information
+**
+** Returns None
+**
+*******************************************************************************/
+void listDump(struct listHead* pList) {
+ struct listNode* pNode = pList->pFirst;
+
+ NXPLOG_NCIHAL_D("Node dump:");
+ while (pNode != NULL) {
+ NXPLOG_NCIHAL_D("- %8p (%8p)", pNode, pNode->pData);
+ pNode = pNode->pNext;
+ }
+
+ return;
+}
+
+/* END Linked list source code */
+
+/****************** Semaphore and mutex helper functions **********************/
+
+static phNxpNciHal_Monitor_t* nxpncihal_monitor = NULL;
+
+/*******************************************************************************
+**
+** Function phNxpNciHal_init_monitor
+**
+** Description Initialize the semaphore monitor
+**
+** Returns Pointer to monitor, otherwise NULL if failed
+**
+*******************************************************************************/
+phNxpNciHal_Monitor_t* phNxpNciHal_init_monitor(void) {
+ NXPLOG_NCIHAL_D("Entering phNxpNciHal_init_monitor");
+
+ if (nxpncihal_monitor == NULL) {
+ nxpncihal_monitor =
+ (phNxpNciHal_Monitor_t*)malloc(sizeof(phNxpNciHal_Monitor_t));
+ }
+
+ if (nxpncihal_monitor != NULL) {
+ memset(nxpncihal_monitor, 0x00, sizeof(phNxpNciHal_Monitor_t));
+
+ if (pthread_mutex_init(&nxpncihal_monitor->reentrance_mutex, NULL) == -1) {
+ NXPLOG_NCIHAL_E("reentrance_mutex creation returned 0x%08x", errno);
+ goto clean_and_return;
+ }
+
+ if (pthread_mutex_init(&nxpncihal_monitor->concurrency_mutex, NULL) == -1) {
+ NXPLOG_NCIHAL_E("concurrency_mutex creation returned 0x%08x", errno);
+ pthread_mutex_destroy(&nxpncihal_monitor->reentrance_mutex);
+ goto clean_and_return;
+ }
+
+ if (listInit(&nxpncihal_monitor->sem_list) != 1) {
+ NXPLOG_NCIHAL_E("Semaphore List creation failed");
+ pthread_mutex_destroy(&nxpncihal_monitor->concurrency_mutex);
+ pthread_mutex_destroy(&nxpncihal_monitor->reentrance_mutex);
+ goto clean_and_return;
+ }
+ } else {
+ NXPLOG_NCIHAL_E("nxphal_monitor creation failed");
+ goto clean_and_return;
+ }
+
+ NXPLOG_NCIHAL_D("Returning with SUCCESS");
+
+ return nxpncihal_monitor;
+
+clean_and_return:
+ NXPLOG_NCIHAL_D("Returning with FAILURE");
+
+ if (nxpncihal_monitor != NULL) {
+ free(nxpncihal_monitor);
+ nxpncihal_monitor = NULL;
+ }
+
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function phNxpNciHal_cleanup_monitor
+**
+** Description Clean up semaphore monitor
+**
+** Returns None
+**
+*******************************************************************************/
+void phNxpNciHal_cleanup_monitor(void) {
+ if (nxpncihal_monitor != NULL) {
+ pthread_mutex_destroy(&nxpncihal_monitor->concurrency_mutex);
+ REENTRANCE_UNLOCK();
+ pthread_mutex_destroy(&nxpncihal_monitor->reentrance_mutex);
+ phNxpNciHal_releaseall_cb_data();
+ listDestroy(&nxpncihal_monitor->sem_list);
+ }
+
+ free(nxpncihal_monitor);
+ nxpncihal_monitor = NULL;
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function phNxpNciHal_get_monitor
+**
+** Description Get monitor
+**
+** Returns Pointer to monitor
+**
+*******************************************************************************/
+phNxpNciHal_Monitor_t* phNxpNciHal_get_monitor(void) {
+ return nxpncihal_monitor;
+}
+
+/* Initialize the callback data */
+NFCSTATUS phNxpNciHal_init_cb_data(phNxpNciHal_Sem_t* pCallbackData,
+ void* pContext) {
+ /* Create semaphore */
+ if (sem_init(&pCallbackData->sem, 0, 0) == -1) {
+ NXPLOG_NCIHAL_E("Semaphore creation failed (errno=0x%08x)", errno);
+ return NFCSTATUS_FAILED;
+ }
+
+ /* Set default status value */
+ pCallbackData->status = NFCSTATUS_FAILED;
+
+ /* Copy the context */
+ pCallbackData->pContext = pContext;
+
+ /* Add to active semaphore list */
+ if (listAdd(&phNxpNciHal_get_monitor()->sem_list, pCallbackData) != 1) {
+ NXPLOG_NCIHAL_E("Failed to add the semaphore to the list");
+ }
+
+ return NFCSTATUS_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function phNxpNciHal_cleanup_cb_data
+**
+** Description Clean up callback data
+**
+** Returns None
+**
+*******************************************************************************/
+void phNxpNciHal_cleanup_cb_data(phNxpNciHal_Sem_t* pCallbackData) {
+ /* Destroy semaphore */
+ if (sem_destroy(&pCallbackData->sem)) {
+ NXPLOG_NCIHAL_E(
+ "phNxpNciHal_cleanup_cb_data: Failed to destroy semaphore "
+ "(errno=0x%08x)",
+ errno);
+ }
+
+ /* Remove from active semaphore list */
+ if (listRemove(&phNxpNciHal_get_monitor()->sem_list, pCallbackData) != 1) {
+ NXPLOG_NCIHAL_E(
+ "phNxpNciHal_cleanup_cb_data: Failed to remove semaphore from the "
+ "list");
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function phNxpNciHal_releaseall_cb_data
+**
+** Description Release all callback data
+**
+** Returns None
+**
+*******************************************************************************/
+void phNxpNciHal_releaseall_cb_data(void) {
+ phNxpNciHal_Sem_t* pCallbackData;
+
+ while (listGetAndRemoveNext(&phNxpNciHal_get_monitor()->sem_list,
+ (void**)&pCallbackData)) {
+ pCallbackData->status = NFCSTATUS_FAILED;
+ sem_post(&pCallbackData->sem);
+ }
+
+ return;
+}
+
+/* END Semaphore and mutex helper functions */
+
+/**************************** Other functions *********************************/
+
+/*******************************************************************************
+**
+** Function phNxpNciHal_print_packet
+**
+** Description Print packet
+**
+** Returns None
+**
+*******************************************************************************/
+void phNxpNciHal_print_packet(const char* pString, const uint8_t* p_data,
+ uint16_t len) {
+ uint32_t i, j;
+ char print_buffer[len * 3 + 1];
+
+ memset(print_buffer, 0, sizeof(print_buffer));
+ for (i = 0; i < len; i++) {
+ snprintf(&print_buffer[i * 2], 3, "%02X", p_data[i]);
+ }
+ if (0 == memcmp(pString, "SEND", 0x04)) {
+ NXPLOG_NCIX_D("len = %3d > %s", len, print_buffer);
+ } else if (0 == memcmp(pString, "RECV", 0x04)) {
+ NXPLOG_NCIR_D("len = %3d > %s", len, print_buffer);
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function phNxpNciHal_emergency_recovery
+**
+** Description Emergency recovery in case of no other way out
+**
+** Returns None
+**
+*******************************************************************************/
+
+void phNxpNciHal_emergency_recovery(void) {
+#if (NFC_NXP_CHIP_TYPE == PN548C2)
+ if (nfcdep_detected && discovery_cmd_len != 0) {
+ pthread_t pthread;
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ if (pthread_create(&pthread, &attr, (void*)phNxpNciHal_core_reset_recovery,
+ NULL) == 0) {
+ return;
+ }
+ }
+#endif
+ NXPLOG_NCIHAL_E("%s: abort()", __func__);
+ abort();
+}
diff --git a/pn54x/utils/phNxpNciHal_utils.h b/pn54x/utils/phNxpNciHal_utils.h
new file mode 100644
index 0000000..3ea33e4
--- /dev/null
+++ b/pn54x/utils/phNxpNciHal_utils.h
@@ -0,0 +1,106 @@
+/*
+ *
+ * Copyright (C) 2013-2014 NXP Semiconductors
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#ifndef _PHNXPNCIHAL_UTILS_H_
+#define _PHNXPNCIHAL_UTILS_H_
+
+#include <assert.h>
+#include <phNfcStatus.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+/********************* Definitions and structures *****************************/
+
+/* List structures */
+struct listNode {
+ void* pData;
+ struct listNode* pNext;
+};
+
+struct listHead {
+ struct listNode* pFirst;
+ pthread_mutex_t mutex;
+};
+
+/* Semaphore handling structure */
+typedef struct phNxpNciHal_Sem {
+ /* Semaphore used to wait for callback */
+ sem_t sem;
+
+ /* Used to store the status sent by the callback */
+ NFCSTATUS status;
+
+ /* Used to provide a local context to the callback */
+ void* pContext;
+
+} phNxpNciHal_Sem_t;
+
+/* Semaphore helper macros */
+#define SEM_WAIT(cb_data) sem_wait(&((cb_data).sem))
+#define SEM_POST(p_cb_data) sem_post(&((p_cb_data)->sem))
+
+/* Semaphore and mutex monitor */
+typedef struct phNxpNciHal_Monitor {
+ /* Mutex protecting native library against reentrance */
+ pthread_mutex_t reentrance_mutex;
+
+ /* Mutex protecting native library against concurrency */
+ pthread_mutex_t concurrency_mutex;
+
+ /* List used to track pending semaphores waiting for callback */
+ struct listHead sem_list;
+
+} phNxpNciHal_Monitor_t;
+
+/************************ Exposed functions ***********************************/
+/* List functions */
+int listInit(struct listHead* pList);
+int listDestroy(struct listHead* pList);
+int listAdd(struct listHead* pList, void* pData);
+int listRemove(struct listHead* pList, void* pData);
+int listGetAndRemoveNext(struct listHead* pList, void** ppData);
+void listDump(struct listHead* pList);
+
+/* NXP NCI HAL utility functions */
+phNxpNciHal_Monitor_t* phNxpNciHal_init_monitor(void);
+void phNxpNciHal_cleanup_monitor(void);
+phNxpNciHal_Monitor_t* phNxpNciHal_get_monitor(void);
+NFCSTATUS phNxpNciHal_init_cb_data(phNxpNciHal_Sem_t* pCallbackData,
+ void* pContext);
+void phNxpNciHal_cleanup_cb_data(phNxpNciHal_Sem_t* pCallbackData);
+void phNxpNciHal_releaseall_cb_data(void);
+void phNxpNciHal_print_packet(const char* pString, const uint8_t* p_data,
+ uint16_t len);
+void phNxpNciHal_emergency_recovery(void);
+
+/* Lock unlock helper macros */
+/* Lock unlock helper macros */
+#define REENTRANCE_LOCK() \
+ if (phNxpNciHal_get_monitor()) \
+ pthread_mutex_lock(&phNxpNciHal_get_monitor()->reentrance_mutex)
+#define REENTRANCE_UNLOCK() \
+ if (phNxpNciHal_get_monitor()) \
+ pthread_mutex_unlock(&phNxpNciHal_get_monitor()->reentrance_mutex)
+#define CONCURRENCY_LOCK() \
+ if (phNxpNciHal_get_monitor()) \
+ pthread_mutex_lock(&phNxpNciHal_get_monitor()->concurrency_mutex)
+#define CONCURRENCY_UNLOCK() \
+ if (phNxpNciHal_get_monitor()) \
+ pthread_mutex_unlock(&phNxpNciHal_get_monitor()->concurrency_mutex)
+
+#endif /* _PHNXPNCIHAL_UTILS_H_ */
diff --git a/pn54x/utils/sparse_crc32.c b/pn54x/utils/sparse_crc32.c
new file mode 100644
index 0000000..1ce4c63
--- /dev/null
+++ b/pn54x/utils/sparse_crc32.c
@@ -0,0 +1,107 @@
+/*-
+ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ */
+
+/*
+ * First, the polynomial itself and its table of feedback terms. The
+ * polynomial is
+ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
+ *
+ * Note that we take it "backwards" and put the highest-order term in
+ * the lowest-order bit. The X^32 term is "implied"; the LSB is the
+ * X^31 term, etc. The X^0 term (usually shown as "+1") results in
+ * the MSB being 1
+ *
+ * Note that the usual hardware shift register implementation, which
+ * is what we're using (we're merely optimizing it by doing eight-bit
+ * chunks at a time) shifts bits into the lowest-order term. In our
+ * implementation, that means shifting towards the right. Why do we
+ * do it this way? Because the calculated CRC must be transmitted in
+ * order from highest-order term to lowest-order term. UARTs transmit
+ * characters in order from LSB to MSB. By storing the CRC this way
+ * we hand it to the UART in the order low-byte to high-byte; the UART
+ * sends each low-bit to hight-bit; and the result is transmission bit
+ * by bit from highest- to lowest-order term without requiring any bit
+ * shuffling on our part. Reception works similarly
+ *
+ * The feedback terms table consists of 256, 32-bit entries. Notes
+ *
+ * The table can be generated at runtime if desired; code to do so
+ * is shown later. It might not be obvious, but the feedback
+ * terms simply represent the results of eight shift/xor opera
+ * tions for all combinations of data and CRC register values
+ *
+ * The values must be right-shifted by eight bits by the "updcrc
+ * logic; the shift must be unsigned (bring in zeroes). On some
+ * hardware you could probably optimize the shift in assembler by
+ * using byte-swap instructions
+ * polynomial $edb88320
+ *
+ *
+ * CRC32 code derived from work by Gary S. Brown.
+ */
+
+/* Code taken from FreeBSD 8 */
+#include <stdint.h>
+
+static uint32_t crc32_tab[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
+
+/*
+ * A function that calculates the CRC-32 based on the table above is
+ * given below for documentation purposes. An equivalent implementation
+ * of this function that's actually used in the kernel can be found
+ * in sys/libkern.h, where it can be inlined.
+ */
+
+uint32_t sparse_crc32(uint32_t crc_in, const void* buf, int size) {
+ const uint8_t* p = buf;
+ uint32_t crc;
+
+ crc = crc_in ^ ~0U;
+ while (size--) crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
+ return crc ^ ~0U;
+}
diff --git a/pn54x/utils/sparse_crc32.h b/pn54x/utils/sparse_crc32.h
new file mode 100644
index 0000000..a776921
--- /dev/null
+++ b/pn54x/utils/sparse_crc32.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef _LIBSPARSE_SPARSE_CRC32_H_
+#define _LIBSPARSE_SPARSE_CRC32_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uint32_t sparse_crc32(uint32_t crc, const void* buf, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif