Merge remote-tracking branch 'aosp/upstream-master' into master1

Test: None
Change-Id: If71c5d24bf7f0cb18afbb8cae07d067468faaed8
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..b4bb535
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# HAL
+st21nfc HAL
diff --git a/libnfc-st.conf b/libnfc-st.conf
new file mode 100644
index 0000000..02b86d6
--- /dev/null
+++ b/libnfc-st.conf
@@ -0,0 +1,115 @@
+########################### Start of libnfc-st.conf ###########################
+
+###############################################################################
+# Application options
+APPL_TRACE_LEVEL=0x05
+# HAL trace flag: 0x00200000
+# HAL NDLC trace flag: 0x00400000
+PROTOCOL_TRACE_LEVEL=0x00600000
+
+###############################################################################
+# File used for NFA storage
+NFA_STORAGE="/data/nfc"
+
+###############################################################################
+# Keep the nfa storage file.
+PRESERVE_STORAGE=1
+
+###############################################################################
+# Force UICC to only listen to the following technology(s).
+# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h.
+# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B.
+# NOTE 1: P2P_LISTEN_TECH_MASK has also an impact on programmed listen mask
+# NOTE 2: If using android 4.4, the listen mode A is always programmed.
+UICC_LISTEN_TECH_MASK=0x00
+
+###############################################################################
+# Inform the system of the maximum number of SE supported.
+# Minimum value is 1 has the UICC may always be used.
+# eSE may not be used depending on phone configuration.
+MAX_NUMBER_OF_SE=0x3
+
+###############################################################################
+# AID for Empty Select command
+# If specified, this AID will be substituted when an Empty SELECT command is
+# detected.  The first byte is the length of the AID.  Maximum length is 16.
+AID_FOR_EMPTY_SELECT={08:A0:00:00:01:51:00:00:00}
+
+###############################################################################
+# Force tag polling for the following technology(s).
+# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h.
+# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B |
+#            NFA_TECHNOLOGY_MASK_F | NFA_TECHNOLOGY_MASK_ISO15693.
+#
+# Notable bits:
+# NFA_TECHNOLOGY_MASK_A	        0x01    /* NFC Technology A             */
+# NFA_TECHNOLOGY_MASK_B	        0x02    /* NFC Technology B             */
+# NFA_TECHNOLOGY_MASK_F	        0x04    /* NFC Technology F             */
+# NFA_TECHNOLOGY_MASK_V       	0x08    /* NFC Technology V             */
+# NFA_TECHNOLOGY_MASK_KOVIO	    0x20    /* Proprietary Technology       */
+# NFA_TECHNOLOGY_MASK_ACTIVE    0x40    /* NFC Technology ACM active mode */
+POLLING_TECH_MASK=0x6F
+
+###############################################################################
+# Force P2P to only listen for the following technology(s).
+# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h.
+# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F | NFA_TECHNOLOGY_MASK_ACTIVE.
+P2P_LISTEN_TECH_MASK=0x45
+
+###############################################################################
+# When screen is turned OFF, specify the desired CE mode to the controller.
+# 0: No card-emulation; DEFAULT
+# 1: Screen-off card-emulation enabled
+CE_ON_SCREEN_OFF_STATE=1
+
+###############################################################################
+# In Switch OFF mode (phone switched-off), specify the desired CE mode to
+# the controller.
+# 0: No card-emulation; DEFAULT
+# 1: Switch-off card-emulation enabled
+CE_ON_SWITCH_OFF_STATE=1
+
+###############################################################################
+# Choose the presence-check algorithm for type-4 tag.  If not defined,
+# the default value is 1.
+# 0  NFA_RW_PRES_CHK_DEFAULT; Let stack selects an algorithm
+# 1  NFA_RW_PRES_CHK_I_BLOCK; ISO-DEP protocol's empty I-block
+# 2  NFA_RW_PRES_CHK_RESET; Deactivate to Sleep, then re-activate
+# 3  NFA_RW_PRES_CHK_RB_CH0; Type-4 tag protocol's ReadBinary command on channel 0
+# 4  NFA_RW_PRES_CHK_RB_CH3; Type-4 tag protocol's ReadBinary command on channel 3
+PRESENCE_CHECK_ALGORITHM=3
+
+###############################################################################
+# Name of the NCI HAL module to use
+# If unset, falls back to nfc_nci.bcm2079x
+NCI_HAL_MODULE="nfc_nci.st21nfc"
+
+###############################################################################
+# White list to be set at startup.
+DEVICE_HOST_WHITE_LIST={2:c0}
+
+###############################################################################
+# When screen is turned off, specify the desired power state of the controller.
+# 0: power-off-sleep state; DEFAULT
+# 1: full-power state
+# 2: screen-off card-emulation (CE4/CE3/CE1 modes are used)
+SCREEN_OFF_POWER_STATE=1
+
+###############################################################################
+# Default Secure Element route id
+DEFAULT_OFFHOST_ROUTE=0x81
+
+###############################################################################
+# Default Secure Element route id for F technology
+DEFAULT_NFCF_ROUTE=0x0
+
+###############################################################################
+# AID_MATCHING constants
+# AID_MATCHING_EXACT_ONLY 0x00
+# AID_MATCHING_EXACT_OR_PREFIX 0x01
+# AID_MATCHING_PREFIX_ONLY 0x02
+AID_MATCHING_MODE=0x1
+
+###############################################################################
+# ST HAL log level
+STNFC_HAL_LOGLEVEL=3
diff --git a/st21nfc/Android.mk b/st21nfc/Android.mk
new file mode 100644
index 0000000..0e9a59b
--- /dev/null
+++ b/st21nfc/Android.mk
@@ -0,0 +1,47 @@
+# Copyright (C) 2011 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_MODULE := nfc_nci.st21nfc.default
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    $(call all-c-files-under, hal) \
+    $(call all-c-files-under, include) \
+    $(call all-c-files-under, gki) \
+    $(call all-c-files-under, adaptation) \
+    $(call all-cpp-files-under, adaptation) \
+    nfc_nci_st21nfc.c \
+    hal_wrapper.c
+
+LOCAL_SHARED_LIBRARIES := liblog libcutils libdl libhardware
+
+LOCAL_CFLAGS := $(D_CFLAGS)
+LOCAL_C_INCLUDES += \
+    $(LOCAL_PATH)/include \
+    $(LOCAL_PATH)/gki/ulinux \
+    $(LOCAL_PATH)/gki/common \
+    $(LOCAL_PATH)/adaptation \
+    $(LOCAL_PATH)/hal \
+
+LOCAL_CFLAGS += -DANDROID \
+        -DST21NFC -DDEBUG
+
+
+
+#
+# nfc_nci.$(TARGET_DEVICE)
+#
+include $(BUILD_SHARED_LIBRARY)
diff --git a/st21nfc/adaptation/android_logmsg.cpp b/st21nfc/adaptation/android_logmsg.cpp
new file mode 100644
index 0000000..36b906c
--- /dev/null
+++ b/st21nfc/adaptation/android_logmsg.cpp
@@ -0,0 +1,106 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1999-2012 Broadcom Corporation
+ * Copyright (C) 2016 ST Microelectronics S.A.
+ *
+ *  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 "android_logmsg.h"
+#include "halcore.h"
+
+void DispHal(const char* title, const void* data, size_t length);
+unsigned char hal_trace_level = STNFC_TRACE_LEVEL_DEBUG;
+
+/*******************************************************************************
+**
+** Function:        InitializeGlobalAppLogLevel
+**
+** Description:     Initialize and get global logging level from
+**                  Android property nfc.app_log_level.
+**
+** Returns:         Global log level:
+**                  STNFC_TRACE_LEVEL_NONE    0     * No trace messages to be
+*                                                     generated
+**                  STNFC_TRACE_LEVEL_ERROR   1     * Error condition trace
+*                                                     messages
+**                  STNFC_TRACE_LEVEL_WARNING 2     * Warning condition trace
+*                                                     messages
+**                  STNFC_TRACE_LEVEL_DEBUG   3     * Debug messages (general)
+**
+**                  STNFC_TRACE_LEVEL_VERBOSE 4     * Verbose messages
+**
+*******************************************************************************/
+unsigned char InitializeSTLogLevel() {
+  unsigned long num = 0;
+  char valueStr[PROPERTY_VALUE_MAX] = {0};
+
+  num = 1;
+  if (GetNumValue(NAME_STNFC_HAL_LOGLEVEL, &num, sizeof(num)))
+    hal_trace_level = (unsigned char)num;
+
+  int len = property_get("nfc.st_hal_log_level", valueStr, "");
+  if (len > 0) {
+    // let Android property override default value
+    sscanf(valueStr, "%lu", &num);
+    hal_trace_level = (unsigned char)num;
+  }
+  STLOG_HAL_D("%s: level=%u", __func__, hal_trace_level);
+  return hal_trace_level;
+}
+
+void DispHal(const char* title, const void* data, size_t length) {
+  uint8_t* d = (uint8_t*)data;
+  char line[100];
+  size_t i, k;
+  bool first_line = true;
+
+  line[0] = 0;
+  if (length == 0) {
+    STLOG_HAL_D("%s", title);
+    return;
+  } else {
+      STLOG_HAL_D("%s: ", title);
+  }
+  for (i = 0, k = 0; i < length; i++, k++) {
+    if (k > 31) {
+      k = 0;
+      if (first_line == true) {
+        first_line = false;
+        if (title[0] == 'R') {
+            STLOG_HAL_D("Rx %s\n", line);
+        } else if (title[0] == 'T') {
+            STLOG_HAL_D("Tx %s\n", line);
+        } else {
+            STLOG_HAL_D("%s\n", line);
+        }
+      } else {
+          STLOG_HAL_D("%s\n", line);
+      }
+      line[k] = 0;
+    }
+    sprintf(&line[k * 3], "%02x ", d[i]);
+  }
+
+  if (first_line == true) {
+    if (title[0] == 'R') {
+        STLOG_HAL_D("Rx %s\n", line);
+    } else if (title[0] == 'T') {
+        STLOG_HAL_D("Tx %s\n", line);
+    } else {
+        STLOG_HAL_D("%s\n", line);
+    }
+  } else {
+      STLOG_HAL_D("%s\n", line);
+  }
+}
diff --git a/st21nfc/adaptation/config.cpp b/st21nfc/adaptation/config.cpp
new file mode 100644
index 0000000..c75d013
--- /dev/null
+++ b/st21nfc/adaptation/config.cpp
@@ -0,0 +1,688 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2011-2012 Broadcom Corporation
+ *  Copyright (C) 2013 ST Microelectronics S.A.
+ *
+ *  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.
+ *
+ *  Modified by ST Microelectronics S.A. (- changed configuration filename)
+ *                                       (- changed getValue and GetStrValue)
+ *
+ *
+ ******************************************************************************/
+#include <stdio.h>
+#include <list>
+#include <string>
+#include <vector>
+#include <log/log.h>
+#include "android_logmsg.h"
+#include <sys/stat.h>
+const char alternative_config_path[] = "";
+const char* transport_config_paths[] = {"/odm/etc/", "/vendor/etc/", "/etc/"};
+
+const int transport_config_path_size =
+    (sizeof(transport_config_paths) / sizeof(transport_config_paths[0]));
+#define config_name "libnfc-st.conf"
+#define extra_config_base "libnfc-st-"
+#define extra_config_ext ".conf"
+#define IsStringValue 0x80000000
+
+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 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;
+  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;
+
+  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:    findConfigFile()
+**
+** Description: find config file among transport_config_paths**
+**
+** Returns:     none
+**
+*******************************************************************************/
+void findConfigFile(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
+  };
+
+  FILE* fd = NULL;
+  string token;
+  string strValue;
+  unsigned long numValue = 0;
+  CNfcParam* pParam = NULL;
+  int i = 0;
+  int base = 0;
+  char c = 0;
+
+  state = BEGIN_LINE;
+  /* open config file, read it into a buffer */
+  if ((fd = fopen(name, "rb")) == NULL) {
+      STLOG_HAL_W("%s Cannot open config file %s\n", __func__, name);
+    if (bResetContent) {
+        STLOG_HAL_W("%s Using default value for all settings\n", __func__);
+      mValidFile = false;
+    }
+    return false;
+  }
+  STLOG_HAL_D("%s Opened %s config %s\n", __func__,
+        (bResetContent ? "base" : "optional"), name);
+
+  mValidFile = true;
+  if (size() > 0) {
+    if (bResetContent)
+      clean();
+    else
+      moveToList();
+  }
+
+  while (!feof(fd) && fread(&c, 1, 1, fd) == 1) {
+    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;
+          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);
+          i=0;
+          break;
+        } else if (c != '\n' && c != '\r') {
+          state = END_LINE;
+          break;
+        }
+      // fal through to numValue to handle numValue
+
+      case NUM_VALUE:
+        if (isDigit(c, base)) {
+          numValue *= base;
+          numValue += getDigitValue(c, base);
+          ++i;
+        } else if (base == 16 &&
+                   (c == ':' || c == '-' || c == ' ' || c == '}')) {
+          if (i > 0) {
+            int n = (i + 1) / 2;
+            while (n-- > 0) {
+              unsigned char c = (numValue >> (n * 8)) & 0xFF;
+              strValue.push_back(c);
+            }
+          }
+          Set(IsStringValue);
+          numValue = 0;
+          i = 0;
+        } else {
+          if (c == '\n' || c == '\r')
+            state = BEGIN_LINE;
+          else
+            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;
+    }
+  }
+
+  fclose(fd);
+
+  moveFromList();
+  return size() > 0;
+}
+
+/*******************************************************************************
+**
+** Function:    CNfcConfig::CNfcConfig()
+**
+** Description: class constructor
+**
+** Returns:     none
+**
+*******************************************************************************/
+CNfcConfig::CNfcConfig() : mValidFile(true) {}
+
+/*******************************************************************************
+**
+** 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;
+      }
+    }
+    findConfigFile(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 || pValue== NULL) return false;
+
+  if (pParam->str_len() > 0) {
+    memset(pValue, 0, len);
+    if (len > pParam->str_len()) len = pParam->str_len();
+    memcpy(pValue, pParam->str_value(), len);
+    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) {
+        STLOG_HAL_D("%s found %s=%s\n", __func__, p_name, (*it)->str_value());
+      } else {
+        STLOG_HAL_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();
+}
+
+/*******************************************************************************
+**
+** 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 GetStrValue(const char* name, char* pValue, unsigned long l) {
+  size_t len = l;
+  CNfcConfig& rConfig = CNfcConfig::GetInstance();
+
+  return rConfig.getValue(name, pValue, len);
+}
+
+/*******************************************************************************
+**
+** Function:    GetNumValue
+**
+** Description: API function for getting a numerical value of a setting
+**
+** Returns:     True if found, otherwise False.
+**
+*******************************************************************************/
+extern "C" int GetNumValue(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 (size_t 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 void resetConfig() {
+  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 {
+    findConfigFile(configName, strPath);
+  }
+
+  CNfcConfig::GetInstance().readConfig(strPath.c_str(), false);
+}
diff --git a/st21nfc/adaptation/i2clayer.c b/st21nfc/adaptation/i2clayer.c
new file mode 100644
index 0000000..7cabc7a
--- /dev/null
+++ b/st21nfc/adaptation/i2clayer.c
@@ -0,0 +1,441 @@
+/** ----------------------------------------------------------------------
+ *
+ * Copyright (C) 2013 ST Microelectronics S.A.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ ----------------------------------------------------------------------*/
+#define _GNU_SOURCE
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <linux/input.h> /* not required for all builds */
+#include <poll.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "halcore.h"
+#include "halcore_private.h"
+#include "android_logmsg.h"
+
+#define ST21NFC_MAGIC 0xEA
+
+#define ST21NFC_GET_WAKEUP _IOR(ST21NFC_MAGIC, 0x01, unsigned int)
+#define ST21NFC_PULSE_RESET _IOR(ST21NFC_MAGIC, 0x02, unsigned int)
+#define ST21NFC_SET_POLARITY_RISING _IOR(ST21NFC_MAGIC, 0x03, unsigned int)
+#define ST21NFC_SET_POLARITY_FALLING _IOR(ST21NFC_MAGIC, 0x04, unsigned int)
+#define ST21NFC_SET_POLARITY_HIGH _IOR(ST21NFC_MAGIC, 0x05, unsigned int)
+#define ST21NFC_SET_POLARITY_LOW _IOR(ST21NFC_MAGIC, 0x06, unsigned int)
+
+#define LINUX_DBGBUFFER_SIZE 300
+
+static int fidI2c = 0;
+static int cmdPipe[2] = {0, 0};
+
+static struct pollfd event_table[2];
+static pthread_t threadHandle = (pthread_t)NULL;
+pthread_mutex_t i2ctransport_mtx = PTHREAD_MUTEX_INITIALIZER;
+
+/**************************************************************************************************
+ *
+ *                                      Private API Declaration
+ *
+ **************************************************************************************************/
+
+static int i2cSetPolarity(int fid, bool low, bool edge);
+static int i2cResetPulse(int fid);
+static int i2cRead(int fid, uint8_t* pvBuffer, int length);
+static int i2cGetGPIOState(int fid);
+static int i2cWrite(int fd, const uint8_t* pvBuffer, int length);
+
+/**************************************************************************************************
+ *
+ *                                      Public API Entry-Points
+ *
+ **************************************************************************************************/
+
+/**
+ * Worker thread for I2C data processing.
+ * On exit of this thread, destroy the HAL thread instance.
+ * @param arg  Handle of the HAL layer
+ */
+static void* I2cWorkerThread(void* arg)
+{
+    bool closeThread = false;
+    HALHANDLE hHAL = (HALHANDLE)arg;
+    STLOG_HAL_V("echo thread started...\n");
+    bool readOk= false;
+
+    do {
+        event_table[0].fd = fidI2c;
+        event_table[0].events = POLLIN;
+        event_table[0].revents = 0;
+
+        event_table[1].fd = cmdPipe[0];
+        event_table[1].events = POLLIN;
+        event_table[1].revents = 0;
+
+        STLOG_HAL_D("echo thread go to sleep...\n");
+
+        int poll_status = poll(event_table, 2, -1);
+
+        if (-1 == poll_status) {
+            STLOG_HAL_E("error in poll call\n");
+            return false;
+        }
+
+        if (event_table[0].revents & POLLIN) {
+            STLOG_HAL_D("echo thread wakeup from chip...\n");
+
+            uint8_t buffer[300];
+
+            do {
+                // load first four bytes:
+                int bytesRead = i2cRead(fidI2c, buffer, 3);
+
+                if (bytesRead == 3) {
+                    if ((buffer[0] != 0x7E) && (buffer[1] != 0x7E)) {
+                        readOk = true;
+                    } else {
+                        if (buffer[1] != 0x7E) {
+                            STLOG_HAL_W("Idle data: 2nd byte is 0x%02x\n, reading next 2 bytes",
+                                  buffer[1]);
+                            buffer[0] = buffer[1];
+                            buffer[1] = buffer[2];
+                            bytesRead = i2cRead(fidI2c, buffer + 2, 1);
+                            if (bytesRead == 1) {
+                                readOk = true;
+                            }
+                        } else if (buffer[2] != 0x7E) {
+                            STLOG_HAL_W("Idle data: 3rd byte is 0x%02x\n, reading next  byte",
+                                  buffer[2]);
+                            buffer[0] = buffer[2];
+                            bytesRead = i2cRead(fidI2c, buffer + 1, 2);
+                            if (bytesRead == 2) {
+                                readOk = true;
+                            }
+                        } else {
+                            STLOG_HAL_W("received idle data\n");
+                        }
+                    }
+
+                    if (readOk == true) {
+                        int remaining = buffer[2];
+
+                        // read and pass to HALCore
+                        bytesRead = i2cRead(fidI2c, buffer + 3, remaining);
+                        if (bytesRead == remaining) {
+                            DispHal("RX DATA", buffer, 3 + bytesRead);
+                            HalSendUpstream(hHAL, buffer, 3 + bytesRead);
+                        } else {
+                            readOk = false;
+                            STLOG_HAL_E("! didn't read expected bytes from i2c\n");
+                        }
+                    }
+
+                } else {
+                    STLOG_HAL_E("! didn't read 3 requested bytes from i2c\n");
+                }
+
+                readOk = false;
+                memset(buffer, 0xca, sizeof(buffer));
+
+                /* read while we have data available */
+            } while (i2cGetGPIOState(fidI2c) == 1);
+        }
+
+        if (event_table[1].revents & POLLIN) {
+            STLOG_HAL_V("thread received command.. \n");
+
+            char cmd = 0;
+            read(cmdPipe[0], &cmd, 1);
+
+            switch (cmd) {
+                case 'X':
+                    STLOG_HAL_D("received close command\n");
+                    closeThread = true;
+                    break;
+
+                case 'W': {
+                    size_t length;
+                    uint8_t buffer[MAX_BUFFER_SIZE];
+                    STLOG_HAL_V("received write command\n");
+                    read(cmdPipe[0], &length, sizeof(length));
+                    if (length <= MAX_BUFFER_SIZE)
+                      {
+                        read(cmdPipe[0], buffer, length);
+                        i2cWrite(fidI2c, buffer, length);
+                      }
+                    else {
+                        STLOG_HAL_E("! received bigger data than expected!! Data not transmitted to NFCC \n");
+                        size_t bytes_read = 1;
+                        // Read all the data to empty but do not use it as not expected
+                        while((bytes_read > 0) && (length > 0))
+                          {
+                            bytes_read = read(cmdPipe[0],buffer,MAX_BUFFER_SIZE);
+                            length = length - bytes_read;
+                          }
+                    }
+                }
+                break;
+            }
+        }
+
+    } while (!closeThread);
+
+    close(fidI2c);
+    close(cmdPipe[0]);
+    close(cmdPipe[1]);
+
+    HalDestroy(hHAL);
+    STLOG_HAL_D("thread exit\n");
+    return 0;
+}
+
+/**
+ * Put command into queue for worker thread to process it.
+ * @param x Command 'X' to close I2C layer or 'W' to write data down to I2C
+ * layer followed by data frame
+ * @param len Size of command or data
+ * @return
+ */
+int I2cWriteCmd(const uint8_t* x, size_t len)
+{
+    return write(cmdPipe[1], x, len);
+}
+
+/**
+ * Initialize the I2C layer.
+ * @param dev NFC NCI device context, NFC callbacks for control/data, HAL handle
+ * @param callb HAL Core callback upon reception on I2C
+ * @param pHandle HAL context handle
+ */
+bool I2cOpenLayer(void* dev, HAL_CALLBACK callb, HALHANDLE* pHandle)
+{
+    uint32_t NoDbgFlag = HAL_FLAG_DEBUG;
+
+      (void) pthread_mutex_lock(&i2ctransport_mtx);
+    fidI2c = open("/dev/st21nfc", O_RDWR);
+    if (fidI2c < 0) {
+        STLOG_HAL_W("unable to open /dev/st21nfc\n");
+        return false;
+    }
+
+    i2cSetPolarity(fidI2c, false, true);
+    i2cResetPulse(fidI2c);
+
+    if ((pipe(cmdPipe) == -1)) {
+        STLOG_HAL_W("unable to open cmdpipe\n");
+        return false;
+    }
+
+    *pHandle = HalCreate(dev, callb, NoDbgFlag);
+
+    if (!*pHandle) {
+        STLOG_HAL_E("failed to create NFC HAL Core \n");
+        return false;
+    }
+
+      (void) pthread_mutex_unlock(&i2ctransport_mtx);
+
+    return (pthread_create(&threadHandle, NULL, I2cWorkerThread, *pHandle) == 0);
+}
+
+/**
+ * Terminates the I2C layer.
+ */
+void I2cCloseLayer()
+{
+    uint8_t cmd = 'X';
+    int ret;
+    ALOGD("%s: enter\n", __func__);
+
+    (void)pthread_mutex_lock(&i2ctransport_mtx);
+
+    if (threadHandle == (pthread_t)NULL)
+        return;
+
+    I2cWriteCmd(&cmd, sizeof(cmd));
+    /* wait for terminate */
+    ret = pthread_join(threadHandle,(void**)NULL);
+    if (ret != 0) {
+        ALOGE("%s: failed to wait for thread (%d)", __func__, ret);
+    }
+    threadHandle = (pthread_t)NULL;
+    (void)pthread_mutex_unlock(&i2ctransport_mtx);
+}
+/**************************************************************************************************
+ *
+ *                                      Private API Definition
+ *
+ **************************************************************************************************/
+/**
+ * Call the st21nfc driver to adjust wake-up polarity.
+ * @param fid File descriptor for NFC device
+ * @param low Polarity (HIGH or LOW)
+ * @param edge Polarity (RISING or FALLING)
+ * @return Result of IOCTL system call (0 if ok)
+ */
+static int i2cSetPolarity(int fid, bool low, bool edge)
+{
+    int result;
+    unsigned int io_code;
+
+    if (low) {
+        if (edge) {
+            io_code = ST21NFC_SET_POLARITY_FALLING;
+        } else {
+            io_code = ST21NFC_SET_POLARITY_LOW;
+        }
+
+    } else {
+        if (edge) {
+            io_code = ST21NFC_SET_POLARITY_RISING;
+        } else {
+            io_code = ST21NFC_SET_POLARITY_HIGH;
+        }
+    }
+
+    if (-1 == (result = ioctl(fid, io_code, NULL))) {
+        result = -1;
+    }
+
+    return result;
+} /* i2cSetPolarity*/
+
+/**
+ * Call the st21nfc driver to generate a 30ms pulse on RESET line.
+ * @param fid File descriptor for NFC device
+ * @return Result of IOCTL system call (0 if ok)
+ */
+static int i2cResetPulse(int fid)
+{
+    int result;
+
+    if (-1 == (result = ioctl(fid, ST21NFC_PULSE_RESET, NULL))) {
+        result = -1;
+    }
+    STLOG_HAL_D("! i2cResetPulse!!, result = %d", result);
+    return result;
+} /* i2cResetPulse*/
+
+/**
+ * Write data to st21nfc, on failure do max 3 retries.
+ * @param fid File descriptor for NFC device
+ * @param pvBuffer Data to write
+ * @param length Data size
+ * @return 0 if bytes written, -1 if error
+ */
+static int i2cWrite(int fid, const uint8_t* pvBuffer, int length)
+{
+    int retries = 0;
+    int result = 0;
+
+    while (retries < 3) {
+        result = write(fid, pvBuffer, length);
+
+        if (result < 0) {
+            char msg[LINUX_DBGBUFFER_SIZE];
+
+            strerror_r(errno, msg, LINUX_DBGBUFFER_SIZE);
+            STLOG_HAL_W("! i2cWrite!!, errno is '%s'", msg);
+            usleep(4000);
+            retries++;
+        } else if (result > 0) {
+            result = 0;
+            return result;
+        } else {
+            STLOG_HAL_W("write on i2c failed, retrying\n");
+            usleep(4000);
+            retries++;
+        }
+    }
+
+    return -1;
+} /* i2cWrite */
+
+/**
+ * Read data from st21nfc, on failure do max 3 retries.
+ *
+ * @param fid File descriptor for NFC device
+ * @param pvBuffer Buffer where to copy read data
+ * @param length Data size to read
+ * @return Length of read data, -1 if error
+ */
+static int i2cRead(int fid, uint8_t* pvBuffer, int length)
+{
+    int retries = 0;
+    int result = -1;
+
+    while ((retries < 3) && (result < 0)) {
+        result = read(fid, pvBuffer, length);
+
+        if (result == -1) {
+            int e = errno;
+            if (e == EAGAIN) {
+                /* File is nonblocking, and no data is available.
+                 * This is not an error condition!
+                 */
+                result = 0;
+                STLOG_HAL_D("## i2cRead - got EAGAIN. No data available. return 0 bytes");
+            } else {
+                /* unexpected result */
+                char msg[LINUX_DBGBUFFER_SIZE];
+                strerror_r(e, msg, LINUX_DBGBUFFER_SIZE);
+                STLOG_HAL_W("## i2cRead returns %d errno %d (%s)", result, e, msg);
+            }
+        }
+
+        if (result < 0) {
+            if (retries < 3) {
+                /* delays are different and increasing for the three retries. */
+                static const uint8_t delayTab[] = {2, 3, 5};
+                int delay = delayTab[retries];
+
+                retries++;
+                STLOG_HAL_W("## i2cRead retry %d/3 in %d milliseconds.", retries, delay);
+                usleep(delay * 1000);
+                continue;
+            }
+        }
+    }
+    return result;
+} /* i2cRead */
+
+/**
+ * Get the activation status of wake-up pin from st21nfc.
+ *  The decision 'active' depends on selected polarity.
+ *  The decision is handled inside the driver(st21nfc).
+ * @param fid File descriptor for NFC device
+ * @return
+ *  Result < 0:     Error condition
+ *  Result > 0:     Pin active
+ *  Result = 0:     Pin not active
+ */
+static int i2cGetGPIOState(int fid)
+{
+    int result;
+
+    if (-1 == (result = ioctl(fid, ST21NFC_GET_WAKEUP, NULL))) {
+        result = -1;
+    }
+
+    return result;
+} /* i2cGetGPIOState */
diff --git a/st21nfc/gki/common/gki.h b/st21nfc/gki/common/gki.h
new file mode 100644
index 0000000..083d1bf
--- /dev/null
+++ b/st21nfc/gki/common/gki.h
@@ -0,0 +1,489 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#ifndef GKI_H
+#define GKI_H
+
+#ifdef BUILDCFG
+#if (!defined(NFC_HAL_TARGET) || (NFC_HAL_TARGET == FALSE))
+#include "buildcfg.h"
+#else
+/* Build config when building HAL */
+#include "buildcfg_hal.h"
+#endif
+#endif
+
+/* Include platform-specific over-rides */
+#if (defined(NFC_STANDALONE) && (NFC_STANDALONE == TRUE))
+#include "bt_types.h"
+#include "gki_target.h"
+#elif (defined(NFC_HAL_TARGET) && (NFC_HAL_TARGET == TRUE))
+/* If building NFC HAL, then use hal target file */
+#include "gki_hal_target.h"
+#else
+/* For non-nfc_standalone, include Bluetooth definitions */
+#include "bt_target.h"
+#include "bt_types.h"
+#endif
+
+/* Uncomment this line for verbose GKI debugging and buffer tracking */
+/*#define GKI_BUFFER_DEBUG   TRUE*/
+
+/* Error codes */
+#define GKI_SUCCESS 0x00
+#define GKI_FAILURE 0x01
+#define GKI_INVALID_TASK 0xF0
+#define GKI_INVALID_POOL 0xFF
+
+/************************************************************************
+** Mailbox definitions. Each task has 4 mailboxes that are used to
+** send buffers to the task.
+*/
+#define TASK_MBOX_0 0
+#define TASK_MBOX_1 1
+#define TASK_MBOX_2 2
+#define TASK_MBOX_3 3
+
+#define NUM_TASK_MBOX 4
+
+/************************************************************************
+** Event definitions.
+**
+** There are 4 reserved events used to signal messages rcvd in task mailboxes.
+** There are 4 reserved events used to signal timeout events.
+** There are 8 general purpose events available for applications.
+*/
+#define MAX_EVENTS 16
+
+#define TASK_MBOX_0_EVT_MASK 0x0001
+#define TASK_MBOX_1_EVT_MASK 0x0002
+#define TASK_MBOX_2_EVT_MASK 0x0004
+#define TASK_MBOX_3_EVT_MASK 0x0008
+
+#define TIMER_0 0
+#define TIMER_1 1
+#define TIMER_2 2
+#define TIMER_3 3
+
+#define TIMER_0_EVT_MASK 0x0010
+#define TIMER_1_EVT_MASK 0x0020
+#define TIMER_2_EVT_MASK 0x0040
+#define TIMER_3_EVT_MASK 0x0080
+
+#define APPL_EVT_0 8
+#define APPL_EVT_1 9
+#define APPL_EVT_2 10
+#define APPL_EVT_3 11
+#define APPL_EVT_4 12
+#define APPL_EVT_5 13
+#define APPL_EVT_6 14
+#define APPL_EVT_7 15
+
+#define EVENT_MASK(evt) ((uint16_t)(0x0001 << (evt)))
+
+/************************************************************************
+**  Max Time Queue
+**/
+#ifndef GKI_MAX_TIMER_QUEUES
+#define GKI_MAX_TIMER_QUEUES 3
+#endif
+
+/************************************************************************
+**  Macro to determine the pool buffer size based on the GKI POOL ID at compile
+*time.
+**  Pool IDs index from 0 to GKI_NUM_FIXED_BUF_POOLS - 1
+*/
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 1)
+
+#ifndef GKI_POOL_ID_0
+#define GKI_POOL_ID_0 0
+#endif /* ifndef GKI_POOL_ID_0 */
+
+#ifndef GKI_BUF0_SIZE
+#define GKI_BUF0_SIZE 0
+#endif /* ifndef GKI_BUF0_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 1 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 2)
+
+#ifndef GKI_POOL_ID_1
+#define GKI_POOL_ID_1 0
+#endif /* ifndef GKI_POOL_ID_1 */
+
+#ifndef GKI_BUF1_SIZE
+#define GKI_BUF1_SIZE 0
+#endif /* ifndef GKI_BUF1_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 2 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 3)
+
+#ifndef GKI_POOL_ID_2
+#define GKI_POOL_ID_2 0
+#endif /* ifndef GKI_POOL_ID_2 */
+
+#ifndef GKI_BUF2_SIZE
+#define GKI_BUF2_SIZE 0
+#endif /* ifndef GKI_BUF2_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 3 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 4)
+
+#ifndef GKI_POOL_ID_3
+#define GKI_POOL_ID_3 0
+#endif /* ifndef GKI_POOL_ID_4 */
+
+#ifndef GKI_BUF3_SIZE
+#define GKI_BUF3_SIZE 0
+#endif /* ifndef GKI_BUF3_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 4 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 5)
+
+#ifndef GKI_POOL_ID_4
+#define GKI_POOL_ID_4 0
+#endif /* ifndef GKI_POOL_ID_4 */
+
+#ifndef GKI_BUF4_SIZE
+#define GKI_BUF4_SIZE 0
+#endif /* ifndef GKI_BUF4_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 5 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 6)
+
+#ifndef GKI_POOL_ID_5
+#define GKI_POOL_ID_5 0
+#endif /* ifndef GKI_POOL_ID_5 */
+
+#ifndef GKI_BUF5_SIZE
+#define GKI_BUF5_SIZE 0
+#endif /* ifndef GKI_BUF5_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 6 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 7)
+
+#ifndef GKI_POOL_ID_6
+#define GKI_POOL_ID_6 0
+#endif /* ifndef GKI_POOL_ID_6 */
+
+#ifndef GKI_BUF6_SIZE
+#define GKI_BUF6_SIZE 0
+#endif /* ifndef GKI_BUF6_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 7 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 8)
+
+#ifndef GKI_POOL_ID_7
+#define GKI_POOL_ID_7 0
+#endif /* ifndef GKI_POOL_ID_7 */
+
+#ifndef GKI_BUF7_SIZE
+#define GKI_BUF7_SIZE 0
+#endif /* ifndef GKI_BUF7_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 8 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 9)
+
+#ifndef GKI_POOL_ID_8
+#define GKI_POOL_ID_8 0
+#endif /* ifndef GKI_POOL_ID_8 */
+
+#ifndef GKI_BUF8_SIZE
+#define GKI_BUF8_SIZE 0
+#endif /* ifndef GKI_BUF8_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 9 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 10)
+
+#ifndef GKI_POOL_ID_9
+#define GKI_POOL_ID_9 0
+#endif /* ifndef GKI_POOL_ID_9 */
+
+#ifndef GKI_BUF9_SIZE
+#define GKI_BUF9_SIZE 0
+#endif /* ifndef GKI_BUF9_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 10 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 11)
+
+#ifndef GKI_POOL_ID_10
+#define GKI_POOL_ID_10 0
+#endif /* ifndef GKI_POOL_ID_10 */
+
+#ifndef GKI_BUF10_SIZE
+#define GKI_BUF10_SIZE 0
+#endif /* ifndef GKI_BUF10_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 11 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 12)
+
+#ifndef GKI_POOL_ID_11
+#define GKI_POOL_ID_11 0
+#endif /* ifndef GKI_POOL_ID_11 */
+
+#ifndef GKI_BUF11_SIZE
+#define GKI_BUF11_SIZE 0
+#endif /* ifndef GKI_BUF11_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 12 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 13)
+
+#ifndef GKI_POOL_ID_12
+#define GKI_POOL_ID_12 0
+#endif /* ifndef GKI_POOL_ID_12 */
+
+#ifndef GKI_BUF12_SIZE
+#define GKI_BUF12_SIZE 0
+#endif /* ifndef GKI_BUF12_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 13 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 14)
+
+#ifndef GKI_POOL_ID_13
+#define GKI_POOL_ID_13 0
+#endif /* ifndef GKI_POOL_ID_13 */
+
+#ifndef GKI_BUF13_SIZE
+#define GKI_BUF13_SIZE 0
+#endif /* ifndef GKI_BUF13_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 14 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 15)
+
+#ifndef GKI_POOL_ID_14
+#define GKI_POOL_ID_14 0
+#endif /* ifndef GKI_POOL_ID_14 */
+
+#ifndef GKI_BUF14_SIZE
+#define GKI_BUF14_SIZE 0
+#endif /* ifndef GKI_BUF14_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 15 */
+
+#if (GKI_NUM_FIXED_BUF_POOLS < 16)
+
+#ifndef GKI_POOL_ID_15
+#define GKI_POOL_ID_15 0
+#endif /* ifndef GKI_POOL_ID_15 */
+
+#ifndef GKI_BUF15_SIZE
+#define GKI_BUF15_SIZE 0
+#endif /* ifndef GKI_BUF15_SIZE */
+
+#endif /* GKI_NUM_FIXED_BUF_POOLS < 16 */
+
+/* Timer list entry callback type
+*/
+typedef void(TIMER_CBACK)(void* p_tle);
+#ifndef TIMER_PARAM_TYPE
+#ifdef WIN2000
+#define TIMER_PARAM_TYPE void*
+#else
+#define TIMER_PARAM_TYPE uint32_t
+#endif
+#endif
+/* Define a timer list entry
+*/
+typedef struct _tle {
+  struct _tle* p_next;
+  struct _tle* p_prev;
+  TIMER_CBACK* p_cback;
+  int32_t ticks;
+  TIMER_PARAM_TYPE param;
+  uint16_t event;
+  uint8_t in_use;
+} TIMER_LIST_ENT;
+
+/* Define a timer list queue
+*/
+typedef struct {
+  TIMER_LIST_ENT* p_first;
+  TIMER_LIST_ENT* p_last;
+  int32_t last_ticks;
+} TIMER_LIST_Q;
+
+/***********************************************************************
+** This queue is a general purpose buffer queue, for application use.
+*/
+typedef struct {
+  void* p_first;
+  void* p_last;
+  uint16_t count;
+} BUFFER_Q;
+
+#define GKI_IS_QUEUE_EMPTY(p_q) ((p_q)->count == 0)
+
+/* Task constants
+*/
+#ifndef TASKPTR
+typedef void (*TASKPTR)(uint32_t);
+#endif
+
+#define GKI_PUBLIC_POOL 0     /* General pool accessible to GKI_getbuf() */
+#define GKI_RESTRICTED_POOL 1 /* Inaccessible pool to GKI_getbuf() */
+
+/***********************************************************************
+** Function prototypes
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Task management
+*/
+extern uint8_t GKI_create_task(TASKPTR, uint8_t, int8_t*, uint16_t*, uint16_t,
+                               void*, void*);
+extern void GKI_exit_task(uint8_t);
+extern uint8_t GKI_get_taskid(void);
+extern void GKI_init(void);
+extern uint8_t* GKI_map_taskname(uint8_t);
+extern uint8_t GKI_resume_task(uint8_t);
+extern void GKI_run(void*);
+extern void GKI_stop(void);
+extern uint8_t GKI_suspend_task(uint8_t);
+extern uint8_t GKI_is_task_running(uint8_t);
+extern void GKI_shutdown(void);
+
+/* memory management
+*/
+extern void GKI_shiftdown(uint8_t* p_mem, uint32_t len, uint32_t shift_amount);
+extern void GKI_shiftup(uint8_t* p_dest, uint8_t* p_src, uint32_t len);
+
+/* To send buffers and events between tasks
+*/
+extern uint8_t GKI_isend_event(uint8_t, uint16_t);
+extern void GKI_isend_msg(uint8_t, uint8_t, void*);
+extern void* GKI_read_mbox(uint8_t);
+extern void GKI_send_msg(uint8_t, uint8_t, void*);
+extern uint8_t GKI_send_event(uint8_t, uint16_t);
+
+/* To get and release buffers, change owner and get size
+*/
+extern void GKI_change_buf_owner(void*, uint8_t);
+extern uint8_t GKI_create_pool(uint16_t, uint16_t, uint8_t, void*);
+extern void GKI_delete_pool(uint8_t);
+extern void* GKI_find_buf_start(void*);
+extern void GKI_freebuf(void*);
+#if GKI_BUFFER_DEBUG
+#define GKI_getbuf(size) GKI_getbuf_debug(size, __func__, __LINE__)
+extern void* GKI_getbuf_debug(uint16_t, const char*, int);
+#else
+extern void* GKI_getbuf(uint16_t);
+#endif
+extern uint16_t GKI_get_buf_size(void*);
+#if GKI_BUFFER_DEBUG
+#define GKI_getpoolbuf(id) GKI_getpoolbuf_debug(id, __func__, __LINE__)
+extern void* GKI_getpoolbuf_debug(uint8_t, const char*, int);
+#else
+extern void* GKI_getpoolbuf(uint8_t);
+#endif
+
+extern uint16_t GKI_poolcount(uint8_t);
+extern uint16_t GKI_poolfreecount(uint8_t);
+extern uint16_t GKI_poolutilization(uint8_t);
+extern void GKI_register_mempool(void* p_mem);
+extern uint8_t GKI_set_pool_permission(uint8_t, uint8_t);
+
+/* User buffer queue management
+*/
+extern void* GKI_dequeue(BUFFER_Q*);
+extern void GKI_enqueue(BUFFER_Q*, void*);
+extern void GKI_enqueue_head(BUFFER_Q*, void*);
+extern void* GKI_getfirst(BUFFER_Q*);
+extern void* GKI_getlast(BUFFER_Q*);
+extern void* GKI_getnext(void*);
+extern void GKI_init_q(BUFFER_Q*);
+extern bool GKI_queue_is_empty(BUFFER_Q*);
+extern void* GKI_remove_from_queue(BUFFER_Q*, void*);
+extern uint16_t GKI_get_pool_bufsize(uint8_t);
+
+/* Timer management
+*/
+extern void GKI_add_to_timer_list(TIMER_LIST_Q*, TIMER_LIST_ENT*);
+extern void GKI_delay(uint32_t);
+extern uint32_t GKI_get_tick_count(void);
+extern int8_t* GKI_get_time_stamp(int8_t*);
+extern void GKI_init_timer_list(TIMER_LIST_Q*);
+extern void GKI_init_timer_list_entry(TIMER_LIST_ENT*);
+extern int32_t GKI_ready_to_sleep(void);
+extern void GKI_remove_from_timer_list(TIMER_LIST_Q*, TIMER_LIST_ENT*);
+extern void GKI_start_timer(uint8_t, int32_t, bool);
+extern void GKI_stop_timer(uint8_t);
+extern void GKI_timer_update(int32_t);
+extern uint16_t GKI_update_timer_list(TIMER_LIST_Q*, int32_t);
+extern uint32_t GKI_get_remaining_ticks(TIMER_LIST_Q*, TIMER_LIST_ENT*);
+extern uint16_t GKI_wait(uint16_t, uint32_t);
+
+/* Start and Stop system time tick callback
+ * true for start system tick if time queue is not empty
+ * false to stop system tick if time queue is empty
+*/
+typedef void(SYSTEM_TICK_CBACK)(bool);
+
+/* Time queue management for system ticks
+*/
+extern bool GKI_timer_queue_empty(void);
+extern void GKI_timer_queue_register_callback(SYSTEM_TICK_CBACK*);
+
+/* Disable Interrupts, Enable Interrupts
+*/
+extern void GKI_enable(void);
+extern void GKI_disable(void);
+extern void GKI_sched_lock(void);
+extern void GKI_sched_unlock(void);
+
+/* Allocate (Free) memory from an OS
+*/
+extern void* GKI_os_malloc(uint32_t);
+extern void GKI_os_free(void*);
+
+/* os timer operation */
+extern uint32_t GKI_get_os_tick_count(void);
+
+/* Exception handling
+*/
+extern void GKI_exception(uint16_t, char*);
+
+#if GKI_DEBUG == TRUE
+extern void GKI_PrintBufferUsage(uint8_t* p_num_pools, uint16_t* p_cur_used);
+extern void GKI_PrintBuffer(void);
+extern void GKI_print_task(void);
+#else
+#undef GKI_PrintBufferUsage
+#define GKI_PrintBuffer() NULL
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/st21nfc/gki/ulinux/data_types.h b/st21nfc/gki/ulinux/data_types.h
new file mode 100644
index 0000000..060c870
--- /dev/null
+++ b/st21nfc/gki/ulinux/data_types.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#ifndef DATA_TYPES_H
+#define DATA_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef uint32_t TIME_STAMP;
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+typedef unsigned char UBYTE;
+
+#ifdef __arm
+#define PACKED __packed
+#define INLINE __inline
+#else
+#define PACKED
+#define INLINE
+#endif
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN FALSE
+#endif
+
+#define UINT16_LOW_BYTE(x) ((x)&0xff)
+#define UINT16_HI_BYTE(x) ((x) >> 8)
+
+#endif
diff --git a/st21nfc/hal/halcore.c b/st21nfc/hal/halcore.c
new file mode 100644
index 0000000..1493cac
--- /dev/null
+++ b/st21nfc/hal/halcore.c
@@ -0,0 +1,929 @@
+/** ----------------------------------------------------------------------
+ *
+ * Copyright (C) 2016 ST Microelectronics S.A.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ ----------------------------------------------------------------------*/
+#define LOG_TAG "NfcHal"
+
+
+#include <hardware/nfc.h>
+#include "halcore_private.h"
+#include "android_logmsg.h"
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+extern int I2cWriteCmd(const uint8_t* x, size_t len);
+extern void DispHal(const char* title, const void* data, size_t length);
+
+extern uint32_t ScrProtocolTraceFlag;  // = SCR_PROTO_TRACE_ALL;
+
+// HAL WRAPPER
+static void HalStopTimer(HalInstance* inst);
+
+typedef struct {
+    struct nfc_nci_device nci_device;  // nci_device must be first struct member
+    // below declarations are private variables within HAL
+    nfc_stack_callback_t* p_cback;
+    nfc_stack_data_callback_t* p_data_cback;
+    HALHANDLE hHAL;
+} st21nfc_dev_t;  // beware, is a duplication of structure in nfc_nci_st21nfc.c
+
+/**************************************************************************************************
+ *
+ *                                      Private API Declaration
+ *
+ **************************************************************************************************/
+
+static void* HalWorkerThread(void* arg);
+static inline int sem_wait_nointr(sem_t *sem);
+
+static void HalOnNewUpstreamFrame(HalInstance* inst, const uint8_t* data,
+                                  size_t length);
+static void HalTriggerNextDsPacket(HalInstance* inst);
+static bool HalEnqueueThreadMessage(HalInstance* inst, ThreadMesssage* msg);
+static bool HalDequeueThreadMessage(HalInstance* inst, ThreadMesssage* msg);
+static HalBuffer* HalAllocBuffer(HalInstance* inst);
+static HalBuffer* HalFreeBuffer(HalInstance* inst, HalBuffer* b);
+static uint32_t HalSemWait(sem_t* pSemaphore, uint32_t timeout);
+
+/**************************************************************************************************
+ *
+ *                                      Public API Entry-Points
+ *
+ **************************************************************************************************/
+
+/**
+ * Callback of HAL Core protocol layer.
+ * Invoked by HAL worker thread according to if message is received from NCI
+ * stack or posted by
+ * I2C worker thread.
+ * <p>@param context NFC callbacks for control/data
+ * @param event Next HAL state machine action (send msg to I2C layer or report
+ * data/control/error
+ * to NFC task)
+ * @param length Configure if debug and trace allowed, trace level
+ */
+void HalCoreCallback(void* context, uint32_t event, const void* d,
+                     size_t length)
+{
+    const uint8_t* data = (const uint8_t*)d;
+    uint8_t cmd = 'W';
+
+    st21nfc_dev_t* dev = (st21nfc_dev_t*)context;
+
+    switch (event) {
+        case HAL_EVENT_DSWRITE:
+            STLOG_HAL_V("!! got event HAL_EVENT_DSWRITE for %zu bytes\n", length);
+            DispHal("TX DATA", (data), length);
+
+            // Send write command to IO thread
+            cmd = 'W';
+            I2cWriteCmd(&cmd, sizeof(cmd));
+            I2cWriteCmd((const uint8_t*)&length, sizeof(length));
+            I2cWriteCmd(data, length);
+            break;
+
+        case HAL_EVENT_DATAIND:
+            STLOG_HAL_V("!! got event HAL_EVENT_DATAIND for %zu bytes\n", length);
+
+            if ((length >= 3) && (data[2] != (length - 3))) {
+                STLOG_HAL_W("length is illogical. Header length is %d, packet length %zu\n",
+                      data[2], length);
+            }
+
+            dev->p_data_cback(length, (uint8_t*)data);
+            break;
+
+        case HAL_EVENT_ERROR:
+            STLOG_HAL_E("!! got event HAL_EVENT_ERROR\n");
+            DispHal("Received unexpected HAL message !!!", data, length);
+            break;
+
+        case HAL_EVENT_LINKLOST:
+            STLOG_HAL_E("!! got event HAL_EVENT_LINKLOST or HAL_EVENT_ERROR\n");
+
+            dev->p_cback(HAL_NFC_ERROR_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
+
+            // Write terminate command
+            cmd = 'X';
+            I2cWriteCmd(&cmd, sizeof(cmd));
+            break;
+
+        case HAL_EVENT_TIMER_TIMEOUT:
+            STLOG_HAL_D("!! got event HAL_EVENT_TIMER_TIMEOUT \n");
+            dev->p_cback(HAL_WRAPPER_TIMEOUT_EVT, HAL_NFC_STATUS_OK);
+
+            //            dev->p_data_cback(0, NULL);
+            break;
+    }
+}
+
+/**
+ * Connection to the HAL Core layer.
+ * Set-up HAL context and create HAL worker thread.
+ * <p>@param context NFC NCI device context, NFC callbacks for control/data, HAL
+ * handle
+ * @param callback HAL callback function pointer
+ * @param flags Configure if debug and trace allowed, trace level
+ */
+HALHANDLE HalCreate(void* context, HAL_CALLBACK callback, uint32_t flags)
+{
+    halTraceMask = true;
+
+    if (flags & HAL_FLAG_NO_DEBUG) {
+        halTraceMask = false;
+    }
+
+    STLOG_HAL_V("HalCreate enter\n");
+
+    HalInstance* inst = calloc(1, sizeof(HalInstance));
+
+    if (!inst) {
+        STLOG_HAL_E("!out of memory\n");
+        return NULL;
+    }
+
+    // We need a semaphore to wakeup our protocol thread
+    if (0 != sem_init(&inst->semaphore, 0, 0)) {
+        STLOG_HAL_E("!sem_init failed\n");
+        free(inst);
+        return NULL;
+    }
+
+    // We need a semaphore to manage buffers
+    if (0 != sem_init(&inst->bufferResourceSem, 0, NUM_BUFFERS)) {
+        STLOG_HAL_E("!sem_init failed\n");
+        sem_destroy(&inst->semaphore);
+        free(inst);
+        return NULL;
+    }
+
+    // We need a semaphore to block upstream data indications
+    if (0 != sem_init(&inst->upstreamBlock, 0, 0)) {
+        STLOG_HAL_E("!sem_init failed\n");
+        sem_destroy(&inst->semaphore);
+        sem_destroy(&inst->bufferResourceSem);
+        free(inst);
+        return NULL;
+    }
+
+    // Initialize remaining data-members
+    inst->context = context;
+    inst->callback = callback;
+    inst->flags = flags;
+    inst->freeBufferList = 0;
+    inst->pendingNciList = 0;
+    inst->nciBuffer = 0;
+    inst->ringReadPos = 0;
+    inst->ringWritePos = 0;
+    inst->timeout = HAL_SLEEP_TIMER_DURATION;
+
+    inst->bufferData = calloc(NUM_BUFFERS, sizeof(HalBuffer));
+    if (!inst->bufferData) {
+        STLOG_HAL_E("!failed to allocate memory\n");
+        sem_destroy(&inst->semaphore);
+        sem_destroy(&inst->bufferResourceSem);
+        sem_destroy(&inst->upstreamBlock);
+        free(inst);
+        return NULL;
+    }
+
+    // Concatenate the buffers into a linked list for easy access
+    size_t i;
+    for (i = 0; i < NUM_BUFFERS; i++) {
+        HalBuffer* b = &inst->bufferData[i];
+        b->next = inst->freeBufferList;
+        inst->freeBufferList = b;
+    }
+
+    if (0 != pthread_mutex_init(&inst->hMutex, 0))
+      {
+        STLOG_HAL_E("!failed to initialize Mutex \n");
+        sem_destroy(&inst->semaphore);
+        sem_destroy(&inst->bufferResourceSem);
+        sem_destroy(&inst->upstreamBlock);
+        free(inst->bufferData);
+        free(inst);
+        return NULL;
+      }
+
+    // Spawn the thread
+    if (0 != pthread_create(&inst->thread, NULL, HalWorkerThread, inst)) {
+        STLOG_HAL_E("!failed to spawn workerthread \n");
+        sem_destroy(&inst->semaphore);
+        sem_destroy(&inst->bufferResourceSem);
+        sem_destroy(&inst->upstreamBlock);
+        pthread_mutex_destroy(&inst->hMutex);
+        free(inst->bufferData);
+        free(inst);
+        return NULL;
+    }
+
+    STLOG_HAL_V("HalCreate exit\n");
+    return (HALHANDLE)inst;
+}
+
+/**
+ * Disconnection of the HAL protocol layer.
+ * Send message to stop the HAL worker thread and wait for it to finish. Free
+ * resources.
+ * @param hHAL HAL handle
+ */
+void HalDestroy(HALHANDLE hHAL)
+{
+    HalInstance* inst = (HalInstance*)hHAL;
+    // Tell the thread that we want to finish
+    ThreadMesssage msg;
+    msg.command = MSG_EXIT_REQUEST;
+    msg.payload = 0;
+    msg.length = 0;
+
+    HalEnqueueThreadMessage(inst, &msg);
+
+    // Wait for thread to finish
+    pthread_join(inst->thread, NULL);
+
+    // Cleanup and exit
+    sem_destroy(&inst->semaphore);
+    sem_destroy(&inst->upstreamBlock);
+    sem_destroy(&inst->bufferResourceSem);
+    pthread_mutex_destroy(&inst->hMutex);
+
+    // Free resources
+    free(inst->bufferData);
+    free(inst);
+
+    STLOG_HAL_V("HalDestroy done\n");
+}
+
+/**
+ * Send an NCI message downstream to HAL protocol layer (DH->NFCC transfer).
+ * Block if more than NUM_BUFFERS (10) transfers are outstanding, otherwise will return immediately.
+ * @param hHAL HAL handle
+ * @param data Data message
+ * @param size Message size
+ */ bool HalSendDownstream(HALHANDLE hHAL, const uint8_t* data, size_t size)
+{
+    // Send an NCI frame downstream. will
+    HalInstance* inst = (HalInstance*)hHAL;
+
+    if ((size <= MAX_BUFFER_SIZE) && (size > 0)) {
+        ThreadMesssage msg;
+        HalBuffer* b = HalAllocBuffer(inst);
+
+        if (!b) {
+            // Should never be reachable
+            return false;
+        }
+
+        memcpy(b->data, data, size);
+        b->length = size;
+
+        msg.command = MSG_TX_DATA;
+        msg.payload = 0;
+        msg.length = 0;
+        msg.buffer = b;
+
+        return HalEnqueueThreadMessage(inst, &msg);
+
+    } else {
+        STLOG_HAL_E("HalSendDownstream size to large %zu instead of %d\n", size,
+              MAX_BUFFER_SIZE);
+        return false;
+    }
+}
+
+// HAL WRAPPER
+/**
+ * Send an NCI message downstream to HAL protocol layer (DH->NFCC transfer).
+ * Block if more than NUM_BUFFERS (10) transfers are outstanding, otherwise will return immediately.
+ * @param hHAL HAL handle
+ * @param data Data message
+ * @param size Message size
+ */ bool HalSendDownstreamTimer(HALHANDLE hHAL, const uint8_t* data,
+                                size_t size, uint8_t duration)
+{
+    // Send an NCI frame downstream. will
+    HalInstance* inst = (HalInstance*)hHAL;
+
+    if ((size <= MAX_BUFFER_SIZE) && (size > 0)) {
+        ThreadMesssage msg;
+        HalBuffer* b = HalAllocBuffer(inst);
+
+        if (!b) {
+            // Should never be reachable
+            return false;
+        }
+
+        memcpy(b->data, data, size);
+        b->length = size;
+
+        msg.command = MSG_TX_DATA_TIMER_START;
+        msg.payload = 0;
+        msg.length = duration;
+        msg.buffer = b;
+
+        return HalEnqueueThreadMessage(inst, &msg);
+
+    } else {
+        STLOG_HAL_E("HalSendDownstreamTimer size to large %zu instead of %d\n", size,
+              MAX_BUFFER_SIZE);
+        return false;
+    }
+}
+
+/**
+ * Send an NCI message downstream to HAL protocol layer (DH->NFCC transfer).
+ * Block if more than NUM_BUFFERS (10) transfers are outstanding, otherwise will
+ * return immediately.
+ * @param hHAL HAL handle
+ * @param data Data message
+ * @param size Message size
+ */
+bool HalSendDownstreamStopTimer(HALHANDLE hHAL)
+{
+    // Send an NCI frame downstream. will
+    HalInstance* inst = (HalInstance*)hHAL;
+
+    HalStopTimer(inst);
+    return 1;
+
+
+}
+
+/**
+ * Send an NCI message upstream to NFC NCI layer (NFCC->DH transfer).
+ * @param hHAL HAL handle
+ * @param data Data message
+ * @param size Message size
+ */ bool HalSendUpstream(HALHANDLE hHAL, const uint8_t* data, size_t size)
+{
+    HalInstance* inst = (HalInstance*)hHAL;
+    if ((size <= MAX_BUFFER_SIZE) && (size > 0)) {
+        ThreadMesssage msg;
+        msg.command = MSG_RX_DATA;
+        msg.payload = data;
+        msg.length = size;
+
+        if (HalEnqueueThreadMessage(inst, &msg)) {
+            // Block until the protocol has taken a copy of the data
+            sem_wait_nointr(&inst->upstreamBlock);
+            return true;
+        }
+        return false;
+    } else {
+        STLOG_HAL_E("HalSendUpstream size to large %zu instead of %d\n", size,
+              MAX_BUFFER_SIZE);
+        return false;
+    }
+}
+
+/**************************************************************************************************
+ *
+ *                                      Private API Definition
+ *
+ **************************************************************************************************/
+/*
+ * Get current time stamp
+ */
+struct timespec HalGetTimestamp(void)
+{
+    struct timespec tm;
+    clock_gettime(CLOCK_REALTIME, &tm);
+    return tm;
+}
+
+int HalTimeDiffInMs(struct timespec start, struct timespec end)
+{
+    struct timespec temp;
+    if ((end.tv_nsec - start.tv_nsec) < 0) {
+        temp.tv_sec = end.tv_sec - start.tv_sec - 1;
+        temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
+    } else {
+        temp.tv_sec = end.tv_sec - start.tv_sec;
+        temp.tv_nsec = end.tv_nsec - start.tv_nsec;
+    }
+
+    return (temp.tv_nsec / 1000000) + (temp.tv_sec * 1000);
+}
+
+
+/**
+ * Determine the next shortest sleep to fulfill the pending timer requirements.
+ * @param inst HAL instance
+ * @param now timespec structure for time definition
+ */
+static uint32_t HalCalcSemWaitingTime(HalInstance* inst, struct timespec* now)
+{
+    // Default to infinite wait time
+    uint32_t result = OS_SYNC_INFINITE;
+
+    if (inst->timer.active) {
+        int delta =
+            inst->timer.duration - HalTimeDiffInMs(inst->timer.startTime, *now);
+
+        if (delta < 0) {
+            // If we have a timer that has already expired, pick a zero wait time
+            result = 0;
+
+        } else if ((uint32_t)delta < result) {
+            // Smaller time difference? If so take it
+            result = delta;
+        }
+    }
+
+    if (result != OS_SYNC_INFINITE) {
+        // Add one millisecond on top of that, so the waiting semaphore will time
+        // out just a moment
+        // after the timer should expire
+        result += 1;
+    }
+
+    return result;
+}
+
+/**************************************************************************************************
+ *
+ *                                     Timer Management
+ *
+ **************************************************************************************************/
+
+static void HalStopTimer(HalInstance* inst)
+{
+    inst->timer.active = false;
+    STLOG_HAL_D("HalStopTimer \n");
+}
+
+static void HalStartTimer(HalInstance* inst, uint32_t duration)
+{
+    STLOG_HAL_D("HalStartTimer \n");
+    inst->timer.startTime = HalGetTimestamp();
+    inst->timer.active = true;
+    inst->timer.duration = duration;
+}
+
+/**************************************************************************************************
+ *
+ *                                     Thread Message Queue
+ *
+ **************************************************************************************************/
+
+/**
+ * Write message pointer to small ring buffer for queuing HAL messages.
+ * @param inst HAL instance
+ * @param msg Message to send
+ * @return true if message properly copied in ring buffer
+ */
+static bool HalEnqueueThreadMessage(HalInstance* inst, ThreadMesssage* msg)
+{
+    // Put a message to the queue
+    int nextWriteSlot;
+    bool result = true;
+
+    pthread_mutex_lock(&inst->hMutex);
+
+    nextWriteSlot = inst->ringWritePos + 1;
+
+    if (nextWriteSlot == HAL_QUEUE_MAX) {
+        nextWriteSlot = 0;
+    }
+
+    // Check that we don't overflow the queue entries
+    if (nextWriteSlot == inst->ringReadPos) {
+        STLOG_HAL_E("HAL thread message ring: RNR (implement me!!)");
+        result = false;
+    }
+
+    if (result) {
+        // inst->ring[nextWriteSlot] = *msg;
+        memcpy(&(inst->ring[nextWriteSlot]), msg, sizeof(ThreadMesssage));
+        inst->ringWritePos = nextWriteSlot;
+    }
+
+    pthread_mutex_unlock(&inst->hMutex);
+
+    if (result) {
+        sem_post(&inst->semaphore);
+    }
+
+    return result;
+}
+
+/**
+ * Remove message pointer from stored ring buffer.
+ * @param inst HAL instance
+ * @param msg Message received
+ * @return true if there is a new message to pull, false otherwise.
+ */
+static bool HalDequeueThreadMessage(HalInstance* inst, ThreadMesssage* msg)
+{
+    int nextCmdIndex;
+    bool result = true;
+    // New data available
+    pthread_mutex_lock(&inst->hMutex);
+
+    // Get new timer read index
+    nextCmdIndex = inst->ringReadPos + 1;
+
+    if (nextCmdIndex == HAL_QUEUE_MAX) {
+        nextCmdIndex = 0;
+    }
+     //check if ring buffer is empty
+    if (inst->ringReadPos == inst->ringWritePos)
+      {
+        STLOG_HAL_E("HAL thread message ring: already read last valid data");
+        result = false;
+      }
+
+    // Get new element from ringbuffer
+    if (result) {
+    memcpy(msg, &(inst->ring[nextCmdIndex]), sizeof(ThreadMesssage));
+    inst->ringReadPos = nextCmdIndex;
+    }
+
+    pthread_mutex_unlock(&inst->hMutex);
+
+    return result;
+}
+
+/**************************************************************************************************
+ *
+ *                                     Buffer/Memory Management
+ *
+ **************************************************************************************************/
+
+/**
+ * Allocate buffer from pre-allocated pool.
+ * @param inst HAL instance
+ * @return Pointer to allocated HAL buffer
+ */
+static HalBuffer* HalAllocBuffer(HalInstance* inst)
+{
+    HalBuffer* b;
+
+    // Wait until we have a buffer resource
+    sem_wait_nointr(&inst->bufferResourceSem);
+
+    pthread_mutex_lock(&inst->hMutex);
+
+    b = inst->freeBufferList;
+    if (b) {
+        inst->freeBufferList = b->next;
+        b->next = 0;
+    }
+
+    pthread_mutex_unlock(&inst->hMutex);
+
+    if (!b) {
+        STLOG_HAL_E(
+            "! unable to allocate buffer resource."
+            "check bufferResourceSem\n");
+    }
+
+    return b;
+}
+
+/**
+ * Return buffer to pool.
+ * @param inst HAL instance
+ * @param b Pointer of HAL buffer to free
+ * @return Pointer of freed HAL buffer
+ */
+static HalBuffer* HalFreeBuffer(HalInstance* inst, HalBuffer* b)
+{
+    pthread_mutex_lock(&inst->hMutex);
+
+    b->next = inst->freeBufferList;
+    inst->freeBufferList = b;
+
+    pthread_mutex_unlock(&inst->hMutex);
+
+    // Unblock treads waiting for a buffer
+    sem_post(&inst->bufferResourceSem);
+
+    return b;
+}
+
+/**************************************************************************************************
+ *
+ *                                     State Machine
+ *
+ **************************************************************************************************/
+
+/**
+ * Event handler for HAL message
+ * @param inst HAL instance
+ * @param e HAL event
+ */
+static void Hal_event_handler(HalInstance* inst, HalEvent e)
+{
+    switch (e) {
+        case EVT_RX_DATA: {
+            // New data packet arrived
+            const uint8_t* nciData;
+            size_t nciLength;
+
+            // Extract raw NCI data from frame
+            nciData = inst->lastUsFrame;
+            nciLength = inst->lastUsFrameSize;
+
+            // Pass received raw NCI data to stack
+            inst->callback(inst->context, HAL_EVENT_DATAIND, nciData, nciLength);
+        }
+        break;
+
+        case EVT_TX_DATA:
+            // NCI data arrived from stack
+            // Send data
+            inst->callback(inst->context, HAL_EVENT_DSWRITE, inst->nciBuffer->data,
+                           inst->nciBuffer->length);
+
+            // Free the buffer
+            HalFreeBuffer(inst, inst->nciBuffer);
+            inst->nciBuffer = 0;
+            break;
+
+        // HAL WRAPPER
+        case EVT_TIMER:
+            inst->callback(inst->context, HAL_EVENT_TIMER_TIMEOUT, NULL, 0);
+            break;
+    }
+}
+
+/**************************************************************************************************
+ *
+ *                                     HAL Worker Thread
+ *
+ **************************************************************************************************/
+
+/**
+ * HAL worker thread to serialize all actions into a single thread.
+ * RX/TX/TIMER are dispatched from here.
+ * @param arg HAL instance arguments
+ */
+static void* HalWorkerThread(void* arg)
+{
+    HalInstance* inst = (HalInstance*)arg;
+    inst->exitRequest = false;
+
+    STLOG_HAL_V("thread running\n");
+
+    while (!inst->exitRequest) {
+        struct timespec now = HalGetTimestamp();
+        uint32_t waitResult =
+            HalSemWait(&inst->semaphore, HalCalcSemWaitingTime(inst, &now));
+
+        switch (waitResult) {
+            case OS_SYNC_TIMEOUT: {
+                // One or more times have expired
+                STLOG_HAL_W("OS_SYNC_TIMEOUT\n");
+                now = HalGetTimestamp();
+
+                // HAL WRAPPER
+                // callback to hal wrapper
+                // Unblock
+                sem_post(&inst->upstreamBlock);
+
+                // Data frame
+                Hal_event_handler(inst, EVT_TIMER);
+            }
+            break;
+
+            case OS_SYNC_RELEASED: {
+                // A message arrived
+                ThreadMesssage msg;
+
+                if (HalDequeueThreadMessage(inst, &msg)) {
+                    switch (msg.command) {
+                        case MSG_EXIT_REQUEST:
+
+                            STLOG_HAL_V("received exit request from upper layer\n");
+                            inst->exitRequest = true;
+                            break;
+
+                        case MSG_TX_DATA:
+                            STLOG_HAL_V("received new NCI data from stack\n");
+
+                            // Attack to end of list
+                            if (!inst->pendingNciList) {
+                                inst->pendingNciList = msg.buffer;
+                                inst->pendingNciList->next = 0;
+                            } else {
+                                // Find last element of the list. b->next is zero for this
+                                // element
+                                HalBuffer* b;
+                                for (b = inst->pendingNciList; b->next; b = b->next) {
+                                };
+
+                                // Concatenate to list
+                                b->next = msg.buffer;
+                                msg.buffer->next = 0;
+                            }
+
+                            // Start transmitting if we're in the correct state
+                            HalTriggerNextDsPacket(inst);
+                            break;
+
+                        // HAL WRAPPER
+                        case MSG_TX_DATA_TIMER_START:
+                            STLOG_HAL_V("received new NCI data from stack, need timer start\n");
+
+                            // Attack to end of list
+                            if (!inst->pendingNciList) {
+                                inst->pendingNciList = msg.buffer;
+                                inst->pendingNciList->next = 0;
+                            } else {
+                                // Find last element of the list. b->next is zero for this
+                                // element
+                                HalBuffer* b;
+                                for (b = inst->pendingNciList; b->next; b = b->next) {
+                                };
+
+                                // Concatenate to list
+                                b->next = msg.buffer;
+                                msg.buffer->next = 0;
+                            }
+
+                            // Start timer
+                            HalStartTimer(inst, msg.length);
+
+                            // Start transmitting if we're in the correct state
+                            HalTriggerNextDsPacket(inst);
+                            break;
+
+                        case MSG_RX_DATA:
+                            STLOG_HAL_D("received new data from CLF\n");
+                            HalOnNewUpstreamFrame(inst, msg.payload, msg.length);
+                            break;
+
+                        default:
+                            STLOG_HAL_E("!received unkown thread message?\n");
+                            break;
+                    }
+                } else {
+                    STLOG_HAL_E("!got wakeup in workerthread, but no message here? ?\n");
+
+            }
+            }
+            break;
+
+            case OS_SYNC_FAILED:
+
+              STLOG_HAL_E(
+                    "!Something went horribly wrong.. The semaphore wait function "
+                    "failed\n");
+                inst->exitRequest = true;
+                break;
+        }
+    }
+
+    STLOG_HAL_D("thread about to exit\n");
+    return NULL;
+}
+
+/**************************************************************************************************
+ *
+ *                                     Misc. Functions
+ *
+ **************************************************************************************************/
+/**
+ *  helper to make sem_t interrupt safe
+ * @param sem_t  semaphore
+ * @return sem_wait return value.
+ */
+
+static inline int sem_wait_nointr(sem_t *sem) {
+  while (sem_wait(sem))
+    if (errno == EINTR) errno = 0;
+    else return -1;
+  return 0;
+}
+
+/**
+ * Handle RX frames here first in HAL context.
+ * @param inst HAL instance
+ * @param data HAL data received from I2C worker thread
+ * @param length Size of HAL data
+ */
+static void HalOnNewUpstreamFrame(HalInstance* inst, const uint8_t* data,
+                                  size_t length)
+{
+    memcpy(inst->lastUsFrame, data, length);
+    inst->lastUsFrameSize = length;
+
+    // Data frame
+    Hal_event_handler(inst, EVT_RX_DATA);
+    // Allow the I2C thread to get the next message (if done early, it may
+    // overwrite before handled)
+    sem_post(&inst->upstreamBlock);
+}
+
+/**
+ * Send out the next queued up buffer for TX if any.
+ * @param inst HAL instance
+ */
+static void HalTriggerNextDsPacket(HalInstance* inst)
+{
+    // Check if we have something to transmit downstream
+    HalBuffer* b = inst->pendingNciList;
+
+    if (b) {
+        // Get the buffer from the pending list
+        inst->pendingNciList = b->next;
+        inst->nciBuffer = b;
+
+        STLOG_HAL_V("trigger transport of next NCI data downstream\n");
+        // Process the new nci frame
+        Hal_event_handler(inst, EVT_TX_DATA);
+
+    } else {
+        STLOG_HAL_V("no new NCI data to transmit, enter wait..\n");
+    }
+}
+
+/*
+ * Wait for given semaphore signaling a specific time or ever
+ * param sem_t * pSemaphore
+ * param uint32_t timeout
+ * return uint32_t
+ */
+static uint32_t HalSemWait(sem_t* pSemaphore, uint32_t timeout)
+{
+    uint32_t result = OS_SYNC_RELEASED;
+    bool gotResult = false;
+
+    if (timeout == OS_SYNC_INFINITE) {
+        while (!gotResult) {
+            if (sem_wait(pSemaphore) == -1) {
+                int e = errno;
+                char msg[200];
+
+                if (e == EINTR) {
+                    STLOG_HAL_W(
+                        "! semaphore (infin) wait interrupted by system signal. re-enter "
+                        "wait");
+                    continue;
+                }
+
+                strerror_r(e, msg, sizeof(msg) - 1);
+                STLOG_HAL_E("! semaphore (infin) wait failed. sem=0x%p, %s", pSemaphore, msg);
+                gotResult = true;
+                result = OS_SYNC_FAILED;
+            } else {
+                gotResult = true;
+            }
+        };
+    } else {
+        struct timespec tm;
+        long oneSecInNs = (int)1e9;
+
+        clock_gettime(CLOCK_REALTIME, &tm);
+
+        /* add timeout (can't overflow): */
+        tm.tv_sec += (timeout / 1000);
+        tm.tv_nsec += ((timeout % 1000) * 1000000);
+
+        /* make sure nanoseconds are below a million */
+        if (tm.tv_nsec >= oneSecInNs) {
+            tm.tv_sec++;
+            tm.tv_nsec -= oneSecInNs;
+        }
+
+        while (!gotResult) {
+            if (sem_timedwait(pSemaphore, &tm) == -1) {
+                int e = errno;
+
+                if (e == EINTR) {
+                    /* interrupted by signal? repeat sem_wait again */
+                    continue;
+                }
+
+                if (e == ETIMEDOUT) {
+                    result = OS_SYNC_TIMEOUT;
+                    gotResult = true;
+                } else {
+                    result = OS_SYNC_FAILED;
+                    gotResult = true;
+                }
+            } else {
+                gotResult = true;
+            }
+        }
+    }
+    return result;
+}
diff --git a/st21nfc/hal/halcore_private.h b/st21nfc/hal/halcore_private.h
new file mode 100644
index 0000000..5bb4853
--- /dev/null
+++ b/st21nfc/hal/halcore_private.h
@@ -0,0 +1,133 @@
+/** ----------------------------------------------------------------------
+ *
+ * Copyright (C) 2016 ST Microelectronics S.A.
+ *
+ * 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 __HALCORE_PRIVATE_
+#define __HALCORE_PRIVATE_
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdint.h>
+#include <time.h>
+#include "halcore.h"
+
+#define MAX_NCIFRAME_PAYLOAD_SIZE 255
+#define MAX_HEADER_SIZE 3
+
+#define MAX_BUFFER_SIZE (MAX_NCIFRAME_PAYLOAD_SIZE + MAX_HEADER_SIZE)
+
+// the three NCI bytes:
+// Octet1 and Octet 2: connection-id and stuff
+// Octet3: length of payload (in bytes)
+
+/* ----------------------------------------------------------------------------------------------*/
+/* ----------------------------------------------------------------------------------------------*/
+/* ----------------------------------------------------------------------------------------------*/
+/* ----------------------------------------------------------------------------------------------*/
+/* ----------------------------------------------------------------------------------------------*/
+
+#define HAL_QUEUE_MAX \
+  8 /* max. # of messages enqueued before going into blocking mode */
+
+/* thread messages  */
+#define MSG_EXIT_REQUEST 0 /* worker thread should terminate itself */
+#define MSG_TX_DATA 1      /* send a message downstream */
+#define MSG_RX_DATA 2      /* a new message has arrived from lower layer */
+
+// HAL _WRAPPER
+#define MSG_TX_DATA_TIMER_START 3
+
+/* number of buffers used for incoming & outgoing data */
+#define NUM_BUFFERS 10
+
+/* constants for the return value of osWait */
+#define OS_SYNC_INFINITE 0xffffffffu
+#define OS_SYNC_RELEASED 0
+#define OS_SYNC_TIMEOUT 1
+#define OS_SYNC_FAILED 0xffffffffu
+
+/* default timeouts */
+#define HAL_SLEEP_TIMER 0
+#define HAL_SLEEP_TIMER_DURATION 500 /* ordinary t1 timeout to resent data */
+
+typedef struct tagHalBuffer {
+    uint8_t data[MAX_BUFFER_SIZE];
+    size_t length;
+    struct tagHalBuffer* next;
+} HalBuffer;
+
+typedef struct tagThreadMessage {
+    uint32_t command;    /* message type / command */
+    const void* payload; /* ptr to message related data item */
+    size_t length;       /* length of above payload */
+    HalBuffer* buffer;   /* buffer object (optional) */
+} ThreadMesssage;
+
+typedef enum {
+    EVT_RX_DATA = 0,
+    EVT_TX_DATA = 1,
+    // HAL WRAPPER
+    EVT_TIMER = 2,
+} HalEvent;
+
+typedef struct tagTimer {
+    struct timespec startTime; /* start time (CLOCK_REALTIME)       */
+    uint32_t duration;         /* timer duration in milliseconds    */
+    bool active;               /* true if timer is currently active */
+} Timer;
+
+typedef struct tagHalInstance {
+    uint32_t flags;
+
+    void* context;
+    HAL_CALLBACK callback;
+
+    /* current timeout values */
+    uint32_t timeout;
+    Timer timer;
+
+    /* threading and runtime support */
+    bool exitRequest;
+    sem_t semaphore;
+    pthread_t thread;
+    pthread_mutex_t hMutex; /* guards the message ringbuffer */
+
+    /* IOBuffers for read/writes */
+    HalBuffer* bufferData;
+    HalBuffer* freeBufferList;
+    HalBuffer* pendingNciList; /* outgoing packages waiting to be processed */
+    HalBuffer* nciBuffer;      /* current buffer in progress */
+    sem_t bufferResourceSem;
+
+    sem_t upstreamBlock;
+
+    /* message ring-buffer */
+    ThreadMesssage ring[HAL_QUEUE_MAX];
+    int ringReadPos;
+    int ringWritePos;
+
+    /* current frame going downstream */
+    uint8_t lastDsFrame[MAX_BUFFER_SIZE];
+    size_t lastDsFrameSize;
+
+    /* current frame from CLF */
+    uint8_t lastUsFrame[MAX_BUFFER_SIZE];
+    size_t lastUsFrameSize;
+
+} HalInstance;
+
+#endif
diff --git a/st21nfc/hal_wrapper.c b/st21nfc/hal_wrapper.c
new file mode 100644
index 0000000..1c2ca51
--- /dev/null
+++ b/st21nfc/hal_wrapper.c
@@ -0,0 +1,194 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2017 ST Microelectronics S.A.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ ******************************************************************************/
+#define LOG_TAG "NfcNciHalWrapper"
+#include <cutils/properties.h>
+#include <errno.h>
+#include <hardware/nfc.h>
+#include <string.h>
+#include "android_logmsg.h"
+#include "halcore.h"
+
+extern void HalCoreCallback(void* context, uint32_t event, const void* d,
+                            size_t length);
+extern bool I2cOpenLayer(void* dev, HAL_CALLBACK callb, HALHANDLE* pHandle);
+extern void I2cCloseLayer();
+
+typedef struct {
+  struct nfc_nci_device nci_device;  // nci_device must be first struct member
+  // below declarations are private variables within HAL
+  nfc_stack_callback_t* p_cback;
+  nfc_stack_data_callback_t* p_data_cback;
+  HALHANDLE hHAL;
+} st21nfc_dev_t;
+
+typedef enum {
+  HAL_WRAPPER_STATE_CLOSED,
+  HAL_WRAPPER_STATE_OPEN,
+  HAL_WRAPPER_STATE_OPEN_CPLT,
+  HAL_WRAPPER_STATE_NFC_ENABLE_ON,
+  HAL_WRAPPER_STATE_READY
+} hal_wrapper_state_e;
+
+static void halWrapperDataCallback(uint16_t data_len, uint8_t* p_data);
+static void halWrapperCallback(uint8_t event, uint8_t event_status);
+
+nfc_stack_callback_t* mHalWrapperCallback = NULL;
+nfc_stack_data_callback_t* mHalWrapperDataCallback = NULL;
+hal_wrapper_state_e mHalWrapperState = HAL_WRAPPER_STATE_CLOSED;
+HALHANDLE mHalHandle = NULL;
+
+bool hal_wrapper_open(st21nfc_dev_t* dev, nfc_stack_callback_t* p_cback,
+                      nfc_stack_data_callback_t* p_data_cback,
+                      HALHANDLE* pHandle) {
+  bool result;
+
+  STLOG_HAL_D("%s", __func__);
+
+  mHalWrapperState = HAL_WRAPPER_STATE_OPEN;
+
+  mHalWrapperCallback = p_cback;
+  mHalWrapperDataCallback = p_data_cback;
+
+  dev->p_data_cback = halWrapperDataCallback;
+  dev->p_cback = halWrapperCallback;
+
+  result = I2cOpenLayer(dev, HalCoreCallback, pHandle);
+
+  if (!result || !(*pHandle)) {
+    return -1;  // We are doomed, stop it here, NOW !
+  }
+
+  mHalHandle = *pHandle;
+
+  return 1;
+}
+
+int hal_wrapper_close(int call_cb) {
+
+  STLOG_HAL_D("%s", __func__);
+
+  mHalWrapperState = HAL_WRAPPER_STATE_CLOSED;
+  I2cCloseLayer();
+  if (call_cb)
+  mHalWrapperCallback(HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK);
+
+  return 1;
+}
+
+void halWrapperDataCallback(uint16_t data_len, uint8_t* p_data) {
+  uint8_t propNfcModeSetCmdOn[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
+  uint8_t coreInitCmd[] = {0x20, 0x01, 0x02, 0x00, 0x00};
+
+  STLOG_HAL_D("%s - mHalWrapperState = %d", __func__, mHalWrapperState);
+
+  switch (mHalWrapperState) {
+    case HAL_WRAPPER_STATE_CLOSED:  // 0
+      break;
+    case HAL_WRAPPER_STATE_OPEN:  // 1
+      // CORE_RESET_NTF
+      if ((p_data[0] == 0x60) && (p_data[1] == 0x00)) {
+        if (p_data[3] == 0x01) {
+          mHalWrapperCallback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_OK);
+          mHalWrapperState = HAL_WRAPPER_STATE_OPEN_CPLT;
+        } else if (p_data[3] == 0xa1)  // Loader mode
+        {
+          mHalWrapperCallback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_FAILED);
+        }
+      } else {
+        mHalWrapperDataCallback(data_len, p_data);
+      }
+      break;
+    case HAL_WRAPPER_STATE_OPEN_CPLT:  // 2
+      // CORE_INIT_RSP
+      if ((p_data[0] == 0x40) && (p_data[1] == 0x01)) {
+      } else if ((p_data[0] == 0x60) && (p_data[1] == 0x06)) {
+        STLOG_HAL_D("%s - Sending PROP_NFC_MODE_SET_CMD", __func__);
+        // Send PROP_NFC_MODE_SET_CMD(ON)
+        if (!HalSendDownstreamTimer(mHalHandle, propNfcModeSetCmdOn,
+                                    sizeof(propNfcModeSetCmdOn), 100)) {
+          STLOG_HAL_E("NFC-NCI HAL: %s  HalSendDownstreamTimer failed", __func__);
+        }
+        mHalWrapperState = HAL_WRAPPER_STATE_NFC_ENABLE_ON;
+      } else {
+        mHalWrapperDataCallback(data_len, p_data);
+      }
+      break;
+    case HAL_WRAPPER_STATE_NFC_ENABLE_ON:  // 3
+      // PROP_NFC_MODE_SET_RSP
+      if ((p_data[0] == 0x4f) && (p_data[1] == 0x02)) {
+        // DO nothing: wait for core_reset_ntf or timer timeout
+      }
+      // CORE_RESET_NTF
+      else if ((p_data[0] == 0x60) && (p_data[1] == 0x00)) {
+        // Stop timer
+        HalSendDownstreamStopTimer(mHalHandle);
+
+        // Send CORE_INIT_CMD
+        STLOG_HAL_D("%s - Sending CORE_INIT_CMD", __func__);
+        if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) {
+           STLOG_HAL_E("NFC-NCI HAL: %s  SendDownstream failed", __func__);
+        }
+      }
+      // CORE_INIT_RSP
+      else if ((p_data[0] == 0x40) && (p_data[1] == 0x01)) {
+        STLOG_HAL_D("%s - NFC mode enabled", __func__);
+        mHalWrapperState = HAL_WRAPPER_STATE_READY;
+        mHalWrapperDataCallback(data_len, p_data);
+      }
+      break;
+    case HAL_WRAPPER_STATE_READY:
+      mHalWrapperDataCallback(data_len, p_data);
+      break;
+  }
+}
+
+static void halWrapperCallback(uint8_t event, uint8_t event_status) {
+  uint8_t coreInitCmd[] = {0x20, 0x01, 0x02, 0x00, 0x00};
+
+  switch (mHalWrapperState) {
+    case HAL_WRAPPER_STATE_CLOSED:
+      break;
+
+    case HAL_WRAPPER_STATE_OPEN:
+      break;
+
+    case HAL_WRAPPER_STATE_OPEN_CPLT:
+      break;
+
+    case HAL_WRAPPER_STATE_NFC_ENABLE_ON:
+      if (event == HAL_WRAPPER_TIMEOUT_EVT) {
+        // timeout
+        // Send CORE_INIT_CMD
+          STLOG_HAL_D("%s - Sending CORE_INIT_CMD", __func__);
+        if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) {
+            STLOG_HAL_E("NFC-NCI HAL: %s  SendDownstream failed", __func__);
+        }
+        return;
+      }
+      break;
+
+    case HAL_WRAPPER_STATE_READY:
+      break;
+
+    default:
+      break;
+  }
+
+  mHalWrapperCallback(event, event_status);
+}
diff --git a/st21nfc/include/android_logmsg.h b/st21nfc/include/android_logmsg.h
new file mode 100644
index 0000000..197d1da
--- /dev/null
+++ b/st21nfc/include/android_logmsg.h
@@ -0,0 +1,95 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2011-2012 Broadcom Corporation
+ *  Copyright (C) 2017 ST Microelectronics S.A.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+/******************************************************************************
+ * Decode NFC packets and print them to ADB log.
+ * If protocol decoder is not present, then decode packets into hex numbers.
+ ******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "data_types.h"
+#include <log/log.h>
+#include <cutils/properties.h>
+
+#define DISP_NCI ProtoDispAdapterDisplayNciPacket
+#define HAL_LOG_TAG "StNfcHal"
+
+extern unsigned char hal_trace_level;
+extern int GetNumValue(const char* name, void* p_value, unsigned long len);
+
+/* #######################
+* Set the log module name in .conf file
+* ########################## */
+#define NAME_STNFC_HAL_LOGLEVEL "STNFC_HAL_LOGLEVEL"
+
+/* #######################
+* Set the logging level
+* ######################## */
+#define STNFC_TRACE_LEVEL_NONE    0x00
+#define STNFC_TRACE_LEVEL_ERROR   0x01
+#define STNFC_TRACE_LEVEL_WARNING 0x02
+#define STNFC_TRACE_LEVEL_DEBUG   0x03
+#define STNFC_TRACE_LEVEL_VERBOSE 0x04
+
+#define STLOG_HAL_V(...)                                       \
+  {                                                              \
+    if (hal_trace_level >= STNFC_TRACE_LEVEL_VERBOSE)  \
+      LOG_PRI(ANDROID_LOG_DEBUG, HAL_LOG_TAG, __VA_ARGS__); \
+  }
+#define STLOG_HAL_D(...)                                       \
+  {                                                              \
+    if (hal_trace_level >= STNFC_TRACE_LEVEL_DEBUG)  \
+      LOG_PRI(ANDROID_LOG_DEBUG, HAL_LOG_TAG, __VA_ARGS__); \
+  }
+#define STLOG_HAL_W(...)                                      \
+  {                                                             \
+    if (hal_trace_level >= STNFC_TRACE_LEVEL_WARNING)  \
+      LOG_PRI(ANDROID_LOG_WARN, HAL_LOG_TAG, __VA_ARGS__); \
+  }
+#define STLOG_HAL_E(...)                                       \
+  {                                                              \
+    if (hal_trace_level >= STNFC_TRACE_LEVEL_ERROR)  \
+      LOG_PRI(ANDROID_LOG_ERROR, HAL_LOG_TAG, __VA_ARGS__); \
+  }
+/*******************************************************************************
+**
+** Function:        InitializeSTLogLevel
+**
+** Description:     Initialize and get global logging level from
+**                  Android property nfc.app_log_level.
+**
+** Returns:         Global log level:
+**                  STNFC_TRACE_LEVEL_NONE    0     * No trace messages to be
+**                                                     generated
+**                  STNFC_TRACE_LEVEL_ERROR   1     * Error condition trace
+**                                                     messages
+**                  STNFC_TRACE_LEVEL_WARNING 2     * Warning condition trace
+**                                                     messages
+**                  STNFC_TRACE_LEVEL_DEBUG   3     * Debug messages (general)
+**
+*******************************************************************************/
+unsigned char InitializeSTLogLevel()  ;
+
+void DispHal(const char* title, const void* data, size_t length);
+
+#ifdef __cplusplus
+};
+#endif
diff --git a/st21nfc/include/halcore.h b/st21nfc/include/halcore.h
new file mode 100644
index 0000000..1df331b
--- /dev/null
+++ b/st21nfc/include/halcore.h
@@ -0,0 +1,106 @@
+/** ----------------------------------------------------------------------
+ *
+ * Copyright (C) 2016 ST Microelectronics S.A.
+ *
+ * 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 __HALCORE_H_
+#define __HALCORE_H_
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+/* events sent from the callback */
+#define HAL_EVENT_DSWRITE 1  /* write raw HAL data downstream   */
+#define HAL_EVENT_DATAIND 2  /* new NCI frame received from CLF  */
+#define HAL_EVENT_LINKLOST 3 /* connection/link lost             */
+#define HAL_EVENT_ERROR 4    /* protocol got into an error state */
+#define HAL_EVENT_JUNKRECEIVED                                        \
+  5 /* protocol signals that junk has been received. resyncronization */
+
+#define HAL_EVENT_TIMER_TIMEOUT 6
+
+/* flags to be passed to HalCreate */
+
+#define HAL_WRAPPER_TIMEOUT_EVT 7
+
+#define HAL_FLAG_NO_DEBUG 0 /* disable debug output */
+#define HAL_FLAG_DEBUG 1    /* enable debug output */
+
+bool halTraceMask;
+pthread_mutex_t debugOutputSem;
+
+#ifdef ANDROID
+#include <android/log.h>
+#define LOG(s)                                               \
+  if (!halTraceMask) {                                       \
+  } else {                                                   \
+    pthread_mutex_lock(&debugOutputSem);                     \
+    __android_log_print(ANDROID_LOG_DEBUG, "NfcHalCore", s); \
+    pthread_mutex_unlock(&debugOutputSem);                   \
+  }
+#define LOGE(s)                                              \
+  {                                                          \
+    pthread_mutex_lock(&debugOutputSem);                     \
+    __android_log_print(ANDROID_LOG_ERROR, "NfcHalCore", s); \
+    pthread_mutex_unlock(&debugOutputSem);                   \
+  }
+#define LOGV(s, ...)                                                      \
+  if (!halTraceMask) {                                                    \
+  } else {                                                                \
+    pthread_mutex_lock(&debugOutputSem);                                  \
+    __android_log_print(ANDROID_LOG_DEBUG, "NfcHalCore", s, __VA_ARGS__); \
+    pthread_mutex_unlock(&debugOutputSem);                                \
+  }
+#define LOGVE(s, ...)                                                     \
+  {                                                                       \
+    pthread_mutex_lock(&debugOutputSem);                                  \
+    __android_log_print(ANDROID_LOG_ERROR, "NfcHalCore", s, __VA_ARGS__); \
+    pthread_mutex_unlock(&debugOutputSem);                                \
+  }
+#else
+#define LOG printf
+#define LOGE printf
+#define LOGV printf
+#define LOGVE printf
+#endif
+
+/* callback function to communicate from HAL Core with the outside world */
+typedef void (*HAL_CALLBACK)(void* context, uint32_t event, const void* data,
+                             size_t length);
+
+/* flags to be passed to HALCreate */
+
+typedef void* HALHANDLE;
+
+HALHANDLE HalCreate(void* context, HAL_CALLBACK callback, uint32_t flags);
+
+void HalDestroy(HALHANDLE hHAL);
+
+/* send an NCI frame from the HOST to the CLF */
+bool HalSendDownstream(HALHANDLE hHAL, const uint8_t* data, size_t size);
+
+// HAL WRAPPER
+bool HalSendDownstreamTimer(HALHANDLE hHAL, const uint8_t* data, size_t size,
+                            uint8_t duration);
+bool HalSendDownstreamStopTimer(HALHANDLE hHAL);
+
+/* send a complete HDLC frame from the CLF to the HOST */
+bool HalSendUpstream(HALHANDLE hHAL, const uint8_t* data, size_t size);
+
+#endif
diff --git a/st21nfc/nfc_nci_st21nfc.c b/st21nfc/nfc_nci_st21nfc.c
new file mode 100644
index 0000000..1d69df1
--- /dev/null
+++ b/st21nfc/nfc_nci_st21nfc.c
@@ -0,0 +1,252 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1999-2012 Broadcom Corporation
+ *  Copyright (C) 2013 ST Microelectronics S.A.
+ *
+ *  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.
+ *
+ *  Modified by ST Microelectronics S.A. (adaptation of nfc_nci.c for ST21NFC
+ *NCI version)
+ *
+ ******************************************************************************/
+
+#include <cutils/properties.h>
+#include <errno.h>
+#include <hardware/nfc.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "android_logmsg.h"
+#include "halcore.h"
+
+extern void HalCoreCallback(void* context, uint32_t event, const void* d,
+                            size_t length);
+extern bool I2cOpenLayer(void* dev, HAL_CALLBACK callb, HALHANDLE* pHandle);
+
+
+typedef struct {
+  struct nfc_nci_device nci_device;  // nci_device must be first struct member
+  // below declarations are private variables within HAL
+  nfc_stack_callback_t* p_cback;
+  nfc_stack_data_callback_t* p_data_cback;
+  HALHANDLE hHAL;
+} st21nfc_dev_t;
+
+char* halVersion = "ST21NFC NCI Version 3.0.5";
+uint8_t cmd_set_nfc_mode_enable[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
+uint8_t hal_is_closed = 1;
+pthread_mutex_t hal_mtx = PTHREAD_MUTEX_INITIALIZER;
+
+uint8_t hal_dta_state = 0;
+
+
+/*
+ * NCI HAL method implementations. These must be overridden
+ */
+
+extern bool hal_wrapper_open(st21nfc_dev_t* dev, nfc_stack_callback_t* p_cback,
+                             nfc_stack_data_callback_t* p_data_cback,
+                             HALHANDLE* pHandle);
+
+extern int hal_wrapper_close(int call_cb);
+
+static int hal_open(const struct nfc_nci_device* p_dev,
+                    nfc_stack_callback_t* p_cback,
+                    nfc_stack_data_callback_t* p_data_cback) {
+  bool result = false;
+
+  STLOG_HAL_D("NFC-NCI HAL: %s %s", __func__, halVersion);
+
+  (void)pthread_mutex_lock(&hal_mtx);
+  st21nfc_dev_t* dev = (st21nfc_dev_t*)p_dev;
+  if (! hal_is_closed ) {
+    hal_wrapper_close(0);
+  }
+  dev->p_cback = p_cback;
+  dev->p_data_cback = p_data_cback;
+
+  hal_dta_state = 0;
+
+  result = hal_wrapper_open(dev, p_cback, p_data_cback, &dev->hHAL);
+
+  if (!result || !dev->hHAL)
+    {
+      dev->p_cback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_FAILED);
+      (void) pthread_mutex_unlock(&hal_mtx);
+      return -1;  // We are doomed, stop it here, NOW !
+    }
+  hal_is_closed = 0;
+  (void)pthread_mutex_unlock(&hal_mtx);
+  return 0;
+}
+
+static int hal_write(const struct nfc_nci_device* p_dev, uint16_t data_len,
+                     const uint8_t* p_data) {
+  STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
+
+  st21nfc_dev_t* dev = (st21nfc_dev_t*)p_dev;
+
+  /* check if HAL is closed */
+  int ret = (int)data_len;
+  (void) pthread_mutex_lock(&hal_mtx);
+  if (hal_is_closed)
+    {
+      ret = 0;
+    }
+
+  if (!ret)
+    {
+      (void) pthread_mutex_unlock(&hal_mtx);
+      return ret;
+    }
+  if (!HalSendDownstream(dev->hHAL, p_data, data_len))
+    {
+      STLOG_HAL_E("NFC-NCI HAL: %s  SendDownstream failed", __func__);
+      (void) pthread_mutex_unlock(&hal_mtx);
+      return 0;
+    }
+  (void) pthread_mutex_unlock(&hal_mtx);
+
+  return ret;
+}
+
+static int hal_core_initialized(const struct nfc_nci_device* p_dev,
+                                uint8_t* p_core_init_rsp_params) {
+  STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
+
+  (void)pthread_mutex_lock(&hal_mtx);
+  st21nfc_dev_t* dev = (st21nfc_dev_t*)p_dev;
+  hal_dta_state = *p_core_init_rsp_params;
+  dev->p_cback(HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_OK);
+  (void) pthread_mutex_unlock(&hal_mtx);
+
+  return 0;  // return != 0 to signal ready immediate
+}
+
+static int hal_pre_discover(__attribute__((unused)) const struct nfc_nci_device* p_dev) {
+  STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
+
+  return 0;  // false if no vendor-specific pre-discovery actions are needed
+}
+
+static int hal_close(__attribute__((unused)) const struct nfc_nci_device* p_dev) {
+  STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
+
+  /* check if HAL is closed */
+  (void)pthread_mutex_lock(&hal_mtx);
+  if ( hal_is_closed ) {
+    (void)pthread_mutex_unlock(&hal_mtx);
+    return 1;
+  }
+  if (hal_wrapper_close(1) == 0) {
+    hal_is_closed = 1;
+    (void)pthread_mutex_unlock(&hal_mtx);
+    return 1;
+  }
+  hal_is_closed = 1;
+  (void)pthread_mutex_unlock(&hal_mtx);
+
+  hal_dta_state = 0;
+
+  return 0;
+}
+
+static int hal_control_granted(__attribute__((unused)) const struct nfc_nci_device* p_dev) {
+  STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
+
+  return 0;
+}
+
+static int hal_power_cycle(const struct nfc_nci_device* p_dev) {
+  STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
+
+  st21nfc_dev_t* dev = (st21nfc_dev_t*)p_dev;
+
+  /* check if HAL is closed */
+  int ret = HAL_NFC_STATUS_OK;
+  (void) pthread_mutex_lock(&hal_mtx);
+  if (hal_is_closed)
+    {
+      ret = HAL_NFC_STATUS_FAILED;
+    }
+
+  if (ret != HAL_NFC_STATUS_OK)
+    {
+      (void) pthread_mutex_unlock(&hal_mtx);
+      return ret;
+    }
+  dev->p_cback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_OK);
+
+  (void) pthread_mutex_unlock(&hal_mtx);
+  return HAL_NFC_STATUS_OK;
+}
+
+/*
+ * Generic device handling below
+ */
+
+/* Close an opened nfc device instance */
+static int nfc_close(hw_device_t* dev) {
+  (void) pthread_mutex_lock(&hal_mtx);
+  free(dev);
+  (void) pthread_mutex_unlock(&hal_mtx);
+  return 0;
+}
+
+static int nfc_open(const hw_module_t* module, const char* name,
+                    hw_device_t** device) {
+
+  if (strcmp(name, NFC_NCI_CONTROLLER) == 0) {
+    st21nfc_dev_t* dev = calloc(1, sizeof(st21nfc_dev_t));
+
+    dev->nci_device.common.tag = HARDWARE_DEVICE_TAG;
+    dev->nci_device.common.version = 0x00010000;  // [31:16] major, [15:0] minor
+    dev->nci_device.common.module = (struct hw_module_t*)module;
+    dev->nci_device.common.close = nfc_close;
+
+    // NCI HAL method pointers
+    dev->nci_device.open = hal_open;
+    dev->nci_device.write = hal_write;
+    dev->nci_device.core_initialized = hal_core_initialized;
+    dev->nci_device.pre_discover = hal_pre_discover;
+    dev->nci_device.close = hal_close;
+    dev->nci_device.control_granted = hal_control_granted;
+    dev->nci_device.power_cycle = hal_power_cycle;
+
+    *device = (hw_device_t*)dev;
+
+    // Initialize and get global logging level
+    InitializeSTLogLevel();
+
+    return 0;
+  } else {
+    return -EINVAL;
+  }
+}
+
+static struct hw_module_methods_t nfc_module_methods = {
+    .open = nfc_open,
+};
+
+struct nfc_nci_module_t HAL_MODULE_INFO_SYM = {
+    .common =
+        {
+            .tag = HARDWARE_MODULE_TAG,
+            .module_api_version = 0x0100,  // [15:8] major, [7:0] minor (1.0)
+            .hal_api_version = 0x00,       // 0 is only valid value
+            .id = "nfc_nci.st21nfc",
+            .name = "ST Micro ST21NFC NCI HW HAL",
+            .author = "ST Microelectronics SA ",
+            .methods = &nfc_module_methods,
+        },
+};