NCI2.0 Support for System Code Based Routing registration.

Bug: 69876039
Test: Perform Felica CE with System code FE0F;
Test: NCI ACTION NTF for SCBR expected with route to eSE.
Change-Id: I45b6646e0c7a5324cd540419e06a5d87b0d6c6fc
(cherry picked from commit cd690c689a8124fd3317b025f7732e8ed3f3bf35)
diff --git a/src/include/nci_defs.h b/src/include/nci_defs.h
index dc70523..9cf7c52 100644
--- a/src/include/nci_defs.h
+++ b/src/include/nci_defs.h
@@ -149,6 +149,7 @@
 #define NCI_STATUS_UNKNOWN_OID 0x08
 #define NCI_STATUS_INVALID_PARAM 0x09
 #define NCI_STATUS_MSG_SIZE_TOO_BIG 0x0A
+#define NCI_STATUS_NOT_SUPPORTED 0x0B
 /* discovery */
 #define NCI_STATUS_ALREADY_STARTED 0xA0
 #define NCI_STATUS_ACTIVATION_FAILED 0xA1
@@ -387,6 +388,7 @@
 /* Protocol based routing  */
 #define NCI_ROUTE_TAG_PROTO 0x01
 #define NCI_ROUTE_TAG_AID 0x02 /* AID routing */
+#define NCI_ROUTE_TAG_SYSCODE 0x03 /* SystemCode routing */
 
 #define NCI_ROUTE_PWR_STATE_ON 0x01 /* The device is on */
 /* The device is switched off */
@@ -531,6 +533,8 @@
 #define NCI_POLLING_DH_DISABLE_MASK 0x00
 /* The DH polling is considered as a enable NFCEE */
 #define NCI_POLLING_DH_ENABLE_MASK 0x01
+/* SCBR support check with Core Init resp OCT1 byte */
+#define NCI_SCBR_MASK 0x10
 
 /* AID matching is allowed when the SELECT AID is longer */
 #define NCI_ROUTE_QUAL_LONG_SELECT 0x10
diff --git a/src/include/nfc_config.h b/src/include/nfc_config.h
index 9229ec9..2e00216 100644
--- a/src/include/nfc_config.h
+++ b/src/include/nfc_config.h
@@ -42,6 +42,7 @@
 #define NAME_NFA_PROPRIETARY_CFG "NFA_PROPRIETARY_CFG"
 #define NAME_DEFAULT_OFFHOST_ROUTE "DEFAULT_OFFHOST_ROUTE"
 #define NAME_DEFAULT_NFCF_ROUTE "DEFAULT_NFCF_ROUTE"
+#define NAME_DEFAULT_SYS_CODE "DEFAULT_SYS_CODE"
 #define NAME_DEFAULT_SYS_CODE_ROUTE "DEFAULT_SYS_CODE_ROUTE"
 #define NAME_DEFAULT_SYS_CODE_PWR_STATE "DEFAULT_SYS_CODE_PWR_STATE"
 #define NAME_DEFAULT_ROUTE "DEFAULT_ROUTE"
diff --git a/src/nfa/dm/nfa_dm_api.cc b/src/nfa/dm/nfa_dm_api.cc
index c17b05d..bec5df4 100644
--- a/src/nfa/dm/nfa_dm_api.cc
+++ b/src/nfa/dm/nfa_dm_api.cc
@@ -759,8 +759,7 @@
   DLOG_IF(INFO, nfc_debug_enabled) << __func__;
 
   /* Post the API message */
-  p_msg = (tNFA_DM_API_SET_RF_DISC_DUR*)GKI_getbuf(
-      sizeof(tNFA_DM_API_SET_RF_DISC_DUR));
+  p_msg = (tNFA_DM_API_SET_RF_DISC_DUR*)GKI_getbuf(sizeof(NFC_HDR));
   if (p_msg != NULL) {
     p_msg->hdr.event = NFA_DM_API_SET_RF_DISC_DURATION_EVT;
 
diff --git a/src/nfa/ee/nfa_ee_act.cc b/src/nfa/ee/nfa_ee_act.cc
index 6d46048..4fd489e 100644
--- a/src/nfa/ee/nfa_ee_act.cc
+++ b/src/nfa/ee/nfa_ee_act.cc
@@ -81,6 +81,18 @@
   *pp += len;
 }
 
+static void add_route_sys_code_tlv(uint8_t** p_buff, uint8_t* p_sys_code_cfg,
+                                   uint8_t sys_code_rt_loc,
+                                   uint8_t sys_code_pwr_cfg) {
+  *(*p_buff)++ = NFC_ROUTE_TAG_SYSCODE | nfa_ee_cb.route_block_control;
+  *(*p_buff)++ = NFA_EE_SYSTEM_CODE_LEN + 2;
+  *(*p_buff)++ = sys_code_rt_loc;
+  *(*p_buff)++ = sys_code_pwr_cfg;
+  /* copy the system code */
+  memcpy(*p_buff, p_sys_code_cfg, NFA_EE_SYSTEM_CODE_LEN);
+  *p_buff += NFA_EE_SYSTEM_CODE_LEN;
+}
+
 const uint8_t nfa_ee_proto_mask_list[NFA_EE_NUM_PROTO] = {
     NFA_PROTOCOL_MASK_T1T, NFA_PROTOCOL_MASK_T2T, NFA_PROTOCOL_MASK_T3T,
     NFA_PROTOCOL_MASK_ISO_DEP, NFA_PROTOCOL_MASK_NFC_DEP};
@@ -209,6 +221,32 @@
 
 /*******************************************************************************
 **
+** Function         nfa_ee_update_route_sys_code_size
+**
+** Description      Update the size required for system code routing
+**                  of the given NFCEE ID.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void nfa_ee_update_route_sys_code_size(tNFA_EE_ECB* p_cb) {
+  p_cb->size_sys_code = 0;
+  if (p_cb->sys_code_cfg_entries) {
+    for (uint8_t xx = 0; xx < p_cb->sys_code_cfg_entries; xx++) {
+      if (p_cb->sys_code_rt_loc_vs_info[xx] & NFA_EE_AE_ROUTE) {
+        /* 4 = 1 (tag) + 1 (len) + 1(nfcee_id) + 1(power cfg) */
+        p_cb->size_sys_code += 4;
+        p_cb->size_sys_code += NFA_EE_SYSTEM_CODE_LEN;
+      }
+    }
+  }
+  DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+      "nfa_ee_update_route_sys_code_size nfcee_id:0x%x size_sys_code:%d",
+      p_cb->nfcee_id, p_cb->size_sys_code);
+}
+
+/*******************************************************************************
+**
 ** Function         nfa_ee_total_lmrt_size
 **
 ** Description      the total listen mode routing table size
@@ -224,11 +262,13 @@
   p_cb = &nfa_ee_cb.ecb[NFA_EE_CB_4_DH];
   lmrt_size += p_cb->size_mask;
   lmrt_size += p_cb->size_aid;
+  lmrt_size += p_cb->size_sys_code;
   p_cb = &nfa_ee_cb.ecb[nfa_ee_cb.cur_ee - 1];
   for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb--) {
     if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE) {
       lmrt_size += p_cb->size_mask;
       lmrt_size += p_cb->size_aid;
+      lmrt_size += p_cb->size_sys_code;
     }
   }
   DLOG_IF(INFO, nfc_debug_enabled)
@@ -378,6 +418,59 @@
   }
 }
 
+static void nfa_ee_add_sys_code_route_to_ecb(tNFA_EE_ECB* p_cb, uint8_t* pp,
+                                             uint8_t* p, uint8_t* p_buff,
+                                             int* p_cur_offset,
+                                             int* p_max_len) {
+  uint8_t num_tlv = *p_buff;
+
+  /* add the SC routing */
+  if (p_cb->sys_code_cfg_entries) {
+    int start_offset = 0;
+    for (int xx = 0; xx < p_cb->sys_code_cfg_entries; xx++) {
+      /* remember the beginning of this SC routing entry, just in case we
+       * need to put it in next command */
+      uint8_t* p_start = pp;
+      /* add one SC entry */
+      if (p_cb->sys_code_rt_loc_vs_info[xx] & NFA_EE_AE_ROUTE) {
+        uint8_t* p_sys_code_cfg = &p_cb->sys_code_cfg[start_offset];
+        if (nfa_ee_is_active(p_cb->sys_code_rt_loc[xx] | NFA_HANDLE_GROUP_EE)) {
+          add_route_sys_code_tlv(&pp, p_sys_code_cfg, p_cb->sys_code_rt_loc[xx],
+                                 p_cb->sys_code_pwr_cfg[xx]);
+          p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_ROUTING;
+          num_tlv++;
+        } else {
+          DLOG_IF(INFO, nfc_debug_enabled)
+              << StringPrintf("%s -  ignoring route loc%x", __func__,
+                              p_cb->sys_code_rt_loc[xx]);
+        }
+      }
+      start_offset += NFA_EE_SYSTEM_CODE_LEN;
+      uint8_t new_size = (uint8_t)(pp - p_start);
+      nfa_ee_check_set_routing(new_size, p_max_len, p_buff, p_cur_offset);
+      if (*p_buff == 0 && (num_tlv > 0x00)) {
+        /* just sent routing command, update local */
+        *p_buff = 1;
+        num_tlv = *p_buff;
+        *p_cur_offset = new_size;
+        pp = p_buff + 1;
+        p = pp;
+        memcpy(p, p_start, new_size);
+        pp += new_size;
+      } else {
+        /* add the new entry */
+        *p_buff = num_tlv;
+        *p_cur_offset += new_size;
+      }
+    }
+    DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+        "nfa_ee_route_add_one_ecb_by_route_order --num_tlv:- %d", num_tlv);
+  } else {
+    DLOG_IF(INFO, nfc_debug_enabled)
+        << StringPrintf("%s - No SC entries available", __func__);
+  }
+}
+
 /*******************************************************************************
 **
 ** Function         nfa_ee_conn_cback
@@ -430,6 +523,45 @@
 
 /*******************************************************************************
 **
+** Function         nfa_ee_find_total_sys_code_len
+**
+** Description      Find the total len in sys_code_cfg from start_entry to the
+**                  last in the given ecb.
+**
+** Returns          void
+**
+*******************************************************************************/
+int nfa_ee_find_total_sys_code_len(tNFA_EE_ECB* p_cb, int start_entry) {
+  int len = 0;
+  if (p_cb->sys_code_cfg_entries > start_entry) {
+    for (int xx = start_entry; xx < p_cb->sys_code_cfg_entries; xx++) {
+      len += NFA_EE_SYSTEM_CODE_LEN;
+    }
+  }
+  return len;
+}
+
+/*******************************************************************************
+**
+** Function         nfa_all_ee_find_total_sys_code_len
+**
+** Description      Find the total len in sys_code_cfg from start_entry to the
+**                  last for all EE and DH.
+**
+** Returns          total length
+**
+*******************************************************************************/
+int nfa_all_ee_find_total_sys_code_len() {
+  int total_len = 0;
+  for (int32_t xx = 0; xx < NFA_EE_NUM_ECBS; xx++) {
+    tNFA_EE_ECB* p_cb = &nfa_ee_cb.ecb[xx];
+    total_len += nfa_ee_find_total_sys_code_len(p_cb, 0);
+  }
+  return total_len;
+}
+
+/*******************************************************************************
+**
 ** Function         nfa_ee_find_aid_offset
 **
 ** Description      Given the AID, find the associated tNFA_EE_ECB and the
@@ -472,6 +604,49 @@
 }
 
 /*******************************************************************************
+ **
+ ** Function         nfa_ee_find_sys_code_offset
+ **
+ ** Description      Given the System Code, find the associated tNFA_EE_ECB and
+ *the
+ **                  offset in sys_code_cfg[]. *p_entry is the index.
+ **
+ ** Returns          void
+ **
+ *******************************************************************************/
+tNFA_EE_ECB* nfa_ee_find_sys_code_offset(uint16_t sys_code, int* p_offset,
+                                         int* p_entry) {
+  tNFA_EE_ECB* p_ret = NULL;
+
+  for (uint8_t xx = 0; xx < NFA_EE_NUM_ECBS; xx++) {
+    tNFA_EE_ECB* p_ecb = &nfa_ee_cb.ecb[xx];
+    uint8_t mask = nfa_ee_ecb_to_mask(p_ecb);
+    if ((nfa_ee_cb.ee_cfged & mask) == 0 || p_ecb->sys_code_cfg_entries == 0) {
+      continue; /*try next ecb*/
+    }
+    if (p_ecb->sys_code_cfg_entries) {
+      uint8_t offset = 0;
+      for (uint8_t yy = 0; yy < p_ecb->sys_code_cfg_entries; yy++) {
+        if ((memcmp(&p_ecb->sys_code_cfg[offset], &sys_code,
+                    NFA_EE_SYSTEM_CODE_LEN) == 0)) {
+          p_ret = p_ecb;
+          if (p_offset) *p_offset = offset;
+          if (p_entry) *p_entry = yy;
+          break;
+        }
+        offset += NFA_EE_SYSTEM_CODE_LEN;
+      }
+
+      if (p_ret) {
+        /* found the entry already */
+        return p_ret;
+      }
+    }
+  }
+  return p_ret;
+}
+
+/*******************************************************************************
 **
 ** Function         nfa_ee_report_event
 **
@@ -909,6 +1084,180 @@
 }
 
 /*******************************************************************************
+ **
+ ** Function         nfa_ee_api_add_sys_code
+ **
+ ** Description      Adds System Code routing configuration from user. When the
+ **                  timer expires, the configuration collected in control block
+ **                  is sent to NFCC
+ **
+ ** Returns          void
+ **
+ *******************************************************************************/
+void nfa_ee_api_add_sys_code(tNFA_EE_MSG* p_data) {
+  tNFA_EE_CBACK_DATA evt_data = {0};
+  tNFA_EE_API_ADD_SYSCODE* p_add = &p_data->add_syscode;
+  tNFA_EE_ECB* p_cb = p_data->cfg_hdr.p_cb;
+
+  DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+      "%s id:0x%x SC:0x%X ", __func__, p_add->nfcee_id, p_add->syscode);
+
+  int offset = 0, entry = 0;
+  tNFA_EE_ECB* p_chk_cb =
+      nfa_ee_find_sys_code_offset(p_add->syscode, &offset, &entry);
+
+  if (p_chk_cb) {
+    DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+        "%s: The SC entry already registered "
+        "for this NFCEE id:0x%02x",
+        __func__, p_add->nfcee_id);
+
+    if (p_chk_cb == p_cb) {
+      p_cb->sys_code_rt_loc_vs_info[entry] |= NFA_EE_AE_ROUTE;
+      uint16_t new_size = nfa_ee_total_lmrt_size();
+      if (new_size > NFC_GetLmrtSize()) {
+        LOG(ERROR) << StringPrintf("Exceeded LMRT size:%d (add SYSCODE)",
+                                   new_size);
+        evt_data.status = NFA_STATUS_BUFFER_FULL;
+        p_cb->sys_code_rt_loc_vs_info[entry] &= ~NFA_EE_AE_ROUTE;
+      } else {
+        p_cb->sys_code_pwr_cfg[entry] = p_add->power_state;
+      }
+    } else {
+      LOG(ERROR) << StringPrintf(
+          "%s: SystemCode entry already registered for different "
+          "NFCEE id:0x%02x",
+          __func__, p_chk_cb->nfcee_id);
+      evt_data.status = NFA_STATUS_REJECTED;
+    }
+  } else {
+    /* Find the total length so far in sys_code_cfg */
+    int total_sc_len = nfa_all_ee_find_total_sys_code_len();
+    /* make sure the control block has enough room to hold this entry */
+    if ((NFA_EE_SYSTEM_CODE_LEN + total_sc_len) >
+        NFA_EE_MAX_SYSTEM_CODE_CFG_LEN) {
+      LOG(ERROR) << StringPrintf(
+          "Exceeded capacity: (NFA_EE_SYSTEM_CODE_LEN:%d + total_sc_len:%d) > "
+          "NFA_EE_MAX_SYSTEM_CODE_CFG_LEN:%d",
+          NFA_EE_SYSTEM_CODE_LEN, total_sc_len, NFA_EE_MAX_SYSTEM_CODE_CFG_LEN);
+      evt_data.status = NFA_STATUS_BUFFER_FULL;
+    } else if (p_cb->sys_code_cfg_entries < NFA_EE_MAX_SYSTEM_CODE_ENTRIES) {
+      /* 6 = 1 (tag) + 1 (len) + 1(nfcee_id) + 1(power cfg) + 2(system code)*/
+      uint16_t new_size =
+          nfa_ee_total_lmrt_size() + NFA_EE_SYSTEM_CODE_TLV_SIZE;
+      if (new_size > NFC_GetLmrtSize()) {
+        LOG(ERROR) << StringPrintf("Exceeded LMRT size:%d", new_size);
+        evt_data.status = NFA_STATUS_BUFFER_FULL;
+      } else {
+        /* add SC entry*/
+        uint32_t p_cb_sc_len = nfa_ee_find_total_sys_code_len(p_cb, 0);
+        p_cb->sys_code_pwr_cfg[p_cb->sys_code_cfg_entries] = p_add->power_state;
+        p_cb->sys_code_rt_loc[p_cb->sys_code_cfg_entries] = p_add->nfcee_id;
+        p_cb->sys_code_rt_loc_vs_info[p_cb->sys_code_cfg_entries] =
+            NFA_EE_AE_ROUTE;
+
+        uint8_t* p = p_cb->sys_code_cfg + p_cb_sc_len;
+        memcpy(p, &p_add->syscode, NFA_EE_SYSTEM_CODE_LEN);
+        p += NFA_EE_SYSTEM_CODE_LEN;
+
+        p_cb->sys_code_cfg_entries++;
+      }
+    } else {
+      LOG(ERROR) << StringPrintf("Exceeded NFA_EE_MAX_SYSTEM_CODE_ENTRIES:%d",
+                                 NFA_EE_MAX_SYSTEM_CODE_ENTRIES);
+      evt_data.status = NFA_STATUS_BUFFER_FULL;
+    }
+  }
+
+  if (evt_data.status == NFA_STATUS_OK) {
+    /* mark SC changed */
+    p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_SYSCODE;
+    nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
+    nfa_ee_update_route_sys_code_size(p_cb);
+    nfa_ee_start_timer();
+  }
+  DLOG_IF(INFO, nfc_debug_enabled)
+      << StringPrintf("%s: status:%d ee_cfged:0x%02x ", __func__,
+                      evt_data.status, nfa_ee_cb.ee_cfged);
+
+  /* report the status of this operation */
+  nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_ADD_SYSCODE_EVT, &evt_data);
+}
+
+/*******************************************************************************
+**
+** Function         nfa_ee_api_remove_sys_code
+**
+** Description      process remove an System Code routing configuration from
+**                  user start a 1 second timer. When the timer expires,
+**                  the configuration collected in control block is sent to NFCC
+**
+** Returns          void
+**
+*******************************************************************************/
+void nfa_ee_api_remove_sys_code(tNFA_EE_MSG* p_data) {
+  tNFA_EE_CBACK_DATA evt_data = {0};
+  tNFA_EE_API_REMOVE_SYSCODE* p_remove = &p_data->rm_syscode;
+
+  DLOG_IF(INFO, nfc_debug_enabled)
+      << StringPrintf("%s SC:0x%x", __func__, p_remove->syscode);
+
+  int offset = 0, entry = 0;
+  tNFA_EE_ECB* p_cb =
+      nfa_ee_find_sys_code_offset(p_data->rm_syscode.syscode, &offset, &entry);
+
+  if (p_cb && p_cb->sys_code_cfg_entries) {
+    DLOG_IF(INFO, nfc_debug_enabled)
+        << StringPrintf("sys_code_rt_loc_vs_info[%d]: 0x%02x", entry,
+                        p_cb->sys_code_rt_loc_vs_info[entry]);
+    /* mark routing and VS changed */
+    if (p_cb->sys_code_rt_loc_vs_info[entry] & NFA_EE_AE_ROUTE)
+      p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_SYSCODE;
+
+    if (p_cb->sys_code_rt_loc_vs_info[entry] & NFA_EE_AE_VS)
+      p_cb->ecb_flags |= NFA_EE_ECB_FLAGS_VS;
+
+    /* remove the system code */
+    if ((entry + 1) < p_cb->sys_code_cfg_entries) {
+      /* not the last entry, move the SC entries in control block */
+      /* Find the total len from the next entry to the last one */
+      int total_len = nfa_ee_find_total_sys_code_len(p_cb, entry + 1);
+
+      int rm_len = NFA_EE_SYSTEM_CODE_LEN;
+
+      DLOG_IF(INFO, nfc_debug_enabled)
+          << StringPrintf("nfa_ee_api_remove_sys_code: rm_len:%d, total_len:%d",
+                          rm_len, total_len);
+
+      GKI_shiftup(&p_cb->sys_code_cfg[offset],
+                  &p_cb->sys_code_cfg[offset + rm_len], total_len);
+
+      total_len = p_cb->sys_code_cfg_entries - entry;
+
+      GKI_shiftup(&p_cb->sys_code_pwr_cfg[entry],
+                  &p_cb->sys_code_pwr_cfg[entry + 1], total_len);
+
+      GKI_shiftup(&p_cb->sys_code_rt_loc_vs_info[entry],
+                  &p_cb->sys_code_rt_loc_vs_info[entry + 1], total_len);
+
+      GKI_shiftup(&p_cb->sys_code_rt_loc[entry],
+                  &p_cb->sys_code_rt_loc[entry + 1], total_len);
+    }
+    /* else the last entry, just reduce the aid_entries by 1 */
+    p_cb->sys_code_cfg_entries--;
+    nfa_ee_cb.ee_cfged |= nfa_ee_ecb_to_mask(p_cb);
+    nfa_ee_update_route_sys_code_size(p_cb);
+    nfa_ee_start_timer();
+  } else {
+    LOG(ERROR) << StringPrintf(
+        "nfa_ee_api_remove_sys_code: The SC entry is not in the database");
+    evt_data.status = NFA_STATUS_INVALID_PARAM;
+  }
+  /* report the status of this operation */
+  nfa_ee_report_event(p_cb->p_ee_cback, NFA_EE_REMOVE_SYSCODE_EVT, &evt_data);
+}
+
+/*******************************************************************************
 **
 ** Function         nfa_ee_api_lmrt_size
 **
@@ -1838,6 +2187,8 @@
   if ((NFA_HANDLE_GROUP_MASK & nfcee_id) == NFA_HANDLE_GROUP_EE)
     nfcee_id &= NFA_HANDLE_MASK;
 
+  if (nfcee_id == NFC_DH_ID) return true;
+
   /* compose output */
   for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++) {
     if ((tNFA_HANDLE)p_cb->nfcee_id == nfcee_id) {
@@ -1964,6 +2315,10 @@
     case NCI_ROUTE_ORDER_AID: {
       nfa_ee_add_aid_route_to_ecb(p_cb, pp, p, ps, p_cur_offset, p_max_len);
     } break;
+    case NCI_ROUTE_ORDER_SYS_CODE: {
+      nfa_ee_add_sys_code_route_to_ecb(p_cb, pp, p, ps, p_cur_offset,
+                                       p_max_len);
+    } break;
     default: {
       DLOG_IF(INFO, nfc_debug_enabled)
           << StringPrintf("%s -  Route type - NA:- %d", __func__, rout_type);
@@ -2177,6 +2532,7 @@
   for (int rt = NCI_ROUTE_ORDER_AID; rt <= NCI_ROUTE_ORDER_TECHNOLOGY; rt++) {
     /* add the routing entries for NFCEEs */
     p_cb = &nfa_ee_cb.ecb[0];
+
     for (xx = 0; (xx < nfa_ee_cb.cur_ee) && check; xx++, p_cb++) {
       if (p_cb->ee_status == NFC_NFCEE_STATUS_ACTIVE) {
         DLOG_IF(INFO, nfc_debug_enabled)
@@ -2228,7 +2584,8 @@
     mask = (1 << xx);
     if (p_cb->tech_switch_on | p_cb->tech_switch_off | p_cb->tech_battery_off |
         p_cb->proto_switch_on | p_cb->proto_switch_off |
-        p_cb->proto_battery_off | p_cb->aid_entries) {
+        p_cb->proto_battery_off | p_cb->aid_entries |
+        p_cb->sys_code_cfg_entries) {
       /* this entry has routing configuration. mark it configured */
       nfa_ee_cb.ee_cfged |= mask;
     }
diff --git a/src/nfa/ee/nfa_ee_api.cc b/src/nfa/ee/nfa_ee_api.cc
index 0209081..0de659e 100644
--- a/src/nfa/ee/nfa_ee_api.cc
+++ b/src/nfa/ee/nfa_ee_api.cc
@@ -24,9 +24,10 @@
 #include <android-base/stringprintf.h>
 #include <base/logging.h>
 
-#include "nfa_ee_api.h"
 #include "nfa_dm_int.h"
+#include "nfa_ee_api.h"
 #include "nfa_ee_int.h"
+#include "nfc_int.h"
 
 using android::base::StringPrintf;
 
@@ -357,7 +358,6 @@
   tNFA_EE_ECB* p_cb;
 
   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
-      ""
       "handle:<0x%x>protocol_mask:<0x%x>/<0x%x>/<0x%x>",
       ee_handle, protocols_switch_on, protocols_switch_off,
       protocols_battery_off);
@@ -495,6 +495,103 @@
 
 /*******************************************************************************
 **
+** Function         NFA_EeAddSystemCodeRouting
+**
+** Description      This function is called to add an system code entry in the
+**                  listen mode routing table in NFCC. The status of this
+**                  operation is reported as the NFA_EE_ADD_SYSCODE_EVT.
+**
+** Note:            If RF discovery is started,
+**                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
+**                  happen before calling this function
+**
+** Note:            NFA_EeUpdateNow() should be called after last NFA-EE
+**                  function to change the listen mode routing is called.
+**
+** Returns          NFA_STATUS_OK if successfully initiated
+**                  NFA_STATUS_FAILED otherwise
+**                  NFA_STATUS_INVALID_PARAM If bad parameter
+**
+*******************************************************************************/
+tNFA_STATUS NFA_EeAddSystemCodeRouting(uint16_t systemcode,
+                                       tNFA_HANDLE ee_handle,
+                                       tNFA_EE_PWR_STATE power_state) {
+  tNFA_STATUS status = NFA_STATUS_FAILED;
+  uint8_t nfcee_id = (uint8_t)(ee_handle & 0xFF);
+  DLOG_IF(INFO, nfc_debug_enabled)
+      << StringPrintf("NFA_EeAddSystemCodeRouting(): handle:<0x%x>", ee_handle);
+  tNFA_EE_ECB* p_cb = nfa_ee_find_ecb(nfcee_id);
+
+  if (p_cb == NULL || systemcode == 0) {
+    LOG(ERROR) << StringPrintf("Bad ee_handle or System Code");
+    status = NFA_STATUS_INVALID_PARAM;
+  } else if ((NFA_GetNCIVersion() != NCI_VERSION_2_0) &&
+             (nfc_cb.isScbrSupported == false)) {
+    LOG(ERROR) << StringPrintf("Invalid NCI Version/SCBR not supported");
+    status = NFA_STATUS_NOT_SUPPORTED;
+  } else {
+    tNFA_EE_API_ADD_SYSCODE* p_msg =
+        (tNFA_EE_API_ADD_SYSCODE*)GKI_getbuf(sizeof(tNFA_EE_API_ADD_SYSCODE));
+    if (p_msg != NULL) {
+      p_msg->hdr.event = NFA_EE_API_ADD_SYSCODE_EVT;
+      p_msg->power_state = power_state;
+      p_msg->nfcee_id = nfcee_id;
+      p_msg->p_cb = p_cb;
+      // adjust endianness of syscode
+      p_msg->syscode = (systemcode & 0x00FF) << 8 | (systemcode & 0xFF00) >> 8;
+      nfa_sys_sendmsg(p_msg);
+      status = NFA_STATUS_OK;
+    }
+  }
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         NFA_EeRemoveSystemCodeRouting
+**
+** Description      This function is called to remove the given System Code
+**                  based entry from the listen mode routing table. The status
+**                  of this operation is reported as the
+**                  NFA_EE_REMOVE_SYSCODE_EVT.
+**
+** Note:            If RF discovery is started,
+**                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
+**                  happen before calling this function
+**
+** Note:            NFA_EeUpdateNow() should be called after last NFA-EE
+**                  function to change the listen mode routing is called.
+**
+** Returns          NFA_STATUS_OK if successfully initiated
+**                  NFA_STATUS_FAILED otherwise
+**                  NFA_STATUS_INVALID_PARAM If bad parameter
+**
+*******************************************************************************/
+tNFA_STATUS NFA_EeRemoveSystemCodeRouting(uint16_t systemcode) {
+  tNFA_STATUS status = NFA_STATUS_FAILED;
+
+  if (systemcode == 0) {
+    LOG(ERROR) << "Bad ee_handle or System Code";
+    status = NFA_STATUS_INVALID_PARAM;
+  } else if ((NFA_GetNCIVersion() != NCI_VERSION_2_0) &&
+             (nfc_cb.isScbrSupported == false)) {
+    LOG(ERROR) << "Invalid NCI Version/SCBR Not supported";
+    status = NFA_STATUS_NOT_SUPPORTED;
+  } else {
+    tNFA_EE_API_REMOVE_SYSCODE* p_msg = (tNFA_EE_API_REMOVE_SYSCODE*)GKI_getbuf(
+        sizeof(tNFA_EE_API_REMOVE_SYSCODE));
+    if (p_msg != NULL) {
+      p_msg->hdr.event = NFA_EE_API_REMOVE_SYSCODE_EVT;
+      p_msg->syscode = (systemcode & 0x00FF) << 8 | (systemcode & 0xFF00) >> 8;
+      nfa_sys_sendmsg(p_msg);
+      status = NFA_STATUS_OK;
+    }
+  }
+  return status;
+}
+
+/*******************************************************************************
+**
 ** Function         NFA_EeGetLmrtRemainingSize
 **
 ** Description      This function is called to get remaining size of the
diff --git a/src/nfa/ee/nfa_ee_main.cc b/src/nfa/ee/nfa_ee_main.cc
index 257ec71..d635338 100644
--- a/src/nfa/ee/nfa_ee_main.cc
+++ b/src/nfa/ee/nfa_ee_main.cc
@@ -52,30 +52,32 @@
 
 const tNFA_EE_SM_ACT nfa_ee_actions[] = {
     /* NFA-EE action function/ internal events */
-    nfa_ee_api_discover,      /* NFA_EE_API_DISCOVER_EVT      */
-    nfa_ee_api_register,      /* NFA_EE_API_REGISTER_EVT      */
-    nfa_ee_api_deregister,    /* NFA_EE_API_DEREGISTER_EVT    */
-    nfa_ee_api_mode_set,      /* NFA_EE_API_MODE_SET_EVT      */
-    nfa_ee_api_set_tech_cfg,  /* NFA_EE_API_SET_TECH_CFG_EVT  */
-    nfa_ee_api_set_proto_cfg, /* NFA_EE_API_SET_PROTO_CFG_EVT */
-    nfa_ee_api_add_aid,       /* NFA_EE_API_ADD_AID_EVT       */
-    nfa_ee_api_remove_aid,    /* NFA_EE_API_REMOVE_AID_EVT    */
-    nfa_ee_api_lmrt_size,     /* NFA_EE_API_LMRT_SIZE_EVT     */
-    nfa_ee_api_update_now,    /* NFA_EE_API_UPDATE_NOW_EVT    */
-    nfa_ee_api_connect,       /* NFA_EE_API_CONNECT_EVT       */
-    nfa_ee_api_send_data,     /* NFA_EE_API_SEND_DATA_EVT     */
-    nfa_ee_api_disconnect,    /* NFA_EE_API_DISCONNECT_EVT    */
-    nfa_ee_nci_disc_rsp,      /* NFA_EE_NCI_DISC_RSP_EVT      */
-    nfa_ee_nci_disc_ntf,      /* NFA_EE_NCI_DISC_NTF_EVT      */
-    nfa_ee_nci_mode_set_rsp,  /* NFA_EE_NCI_MODE_SET_RSP_EVT  */
-    nfa_ee_nci_conn,          /* NFA_EE_NCI_CONN_EVT          */
-    nfa_ee_nci_conn,          /* NFA_EE_NCI_DATA_EVT          */
-    nfa_ee_nci_action_ntf,    /* NFA_EE_NCI_ACTION_NTF_EVT    */
-    nfa_ee_nci_disc_req_ntf,  /* NFA_EE_NCI_DISC_REQ_NTF_EVT  */
-    nfa_ee_nci_wait_rsp,      /* NFA_EE_NCI_WAIT_RSP_EVT      */
-    nfa_ee_rout_timeout,      /* NFA_EE_ROUT_TIMEOUT_EVT      */
-    nfa_ee_discv_timeout,     /* NFA_EE_DISCV_TIMEOUT_EVT     */
-    nfa_ee_lmrt_to_nfcc       /* NFA_EE_CFG_TO_NFCC_EVT       */
+    nfa_ee_api_discover,        /* NFA_EE_API_DISCOVER_EVT      */
+    nfa_ee_api_register,        /* NFA_EE_API_REGISTER_EVT      */
+    nfa_ee_api_deregister,      /* NFA_EE_API_DEREGISTER_EVT    */
+    nfa_ee_api_mode_set,        /* NFA_EE_API_MODE_SET_EVT      */
+    nfa_ee_api_set_tech_cfg,    /* NFA_EE_API_SET_TECH_CFG_EVT  */
+    nfa_ee_api_set_proto_cfg,   /* NFA_EE_API_SET_PROTO_CFG_EVT */
+    nfa_ee_api_add_aid,         /* NFA_EE_API_ADD_AID_EVT       */
+    nfa_ee_api_remove_aid,      /* NFA_EE_API_REMOVE_AID_EVT    */
+    nfa_ee_api_add_sys_code,    /* NFA_EE_API_ADD_SYSCODE_EVT   */
+    nfa_ee_api_remove_sys_code, /* NFA_EE_API_REMOVE_SYSCODE_EVT*/
+    nfa_ee_api_lmrt_size,       /* NFA_EE_API_LMRT_SIZE_EVT     */
+    nfa_ee_api_update_now,      /* NFA_EE_API_UPDATE_NOW_EVT    */
+    nfa_ee_api_connect,         /* NFA_EE_API_CONNECT_EVT       */
+    nfa_ee_api_send_data,       /* NFA_EE_API_SEND_DATA_EVT     */
+    nfa_ee_api_disconnect,      /* NFA_EE_API_DISCONNECT_EVT    */
+    nfa_ee_nci_disc_rsp,        /* NFA_EE_NCI_DISC_RSP_EVT      */
+    nfa_ee_nci_disc_ntf,        /* NFA_EE_NCI_DISC_NTF_EVT      */
+    nfa_ee_nci_mode_set_rsp,    /* NFA_EE_NCI_MODE_SET_RSP_EVT  */
+    nfa_ee_nci_conn,            /* NFA_EE_NCI_CONN_EVT          */
+    nfa_ee_nci_conn,            /* NFA_EE_NCI_DATA_EVT          */
+    nfa_ee_nci_action_ntf,      /* NFA_EE_NCI_ACTION_NTF_EVT    */
+    nfa_ee_nci_disc_req_ntf,    /* NFA_EE_NCI_DISC_REQ_NTF_EVT  */
+    nfa_ee_nci_wait_rsp,        /* NFA_EE_NCI_WAIT_RSP_EVT      */
+    nfa_ee_rout_timeout,        /* NFA_EE_ROUT_TIMEOUT_EVT      */
+    nfa_ee_discv_timeout,       /* NFA_EE_DISCV_TIMEOUT_EVT     */
+    nfa_ee_lmrt_to_nfcc         /* NFA_EE_CFG_TO_NFCC_EVT       */
 };
 
 /*******************************************************************************
@@ -571,6 +573,10 @@
       return "API_ADD_AID";
     case NFA_EE_API_REMOVE_AID_EVT:
       return "API_REMOVE_AID";
+    case NFA_EE_API_ADD_SYSCODE_EVT:
+      return "NFA_EE_API_ADD_SYSCODE_EVT";
+    case NFA_EE_API_REMOVE_SYSCODE_EVT:
+      return "NFA_EE_API_REMOVE_SYSCODE_EVT";
     case NFA_EE_API_LMRT_SIZE_EVT:
       return "API_LMRT_SIZE";
     case NFA_EE_API_UPDATE_NOW_EVT:
diff --git a/src/nfa/include/nfa_api.h b/src/nfa/include/nfa_api.h
index 9791326..1b0f18c 100644
--- a/src/nfa/include/nfa_api.h
+++ b/src/nfa/include/nfa_api.h
@@ -49,6 +49,8 @@
 #define NFA_STATUS_BUFFER_FULL NCI_STATUS_BUFFER_FULL
 /* failed               */
 #define NFA_STATUS_FAILED NCI_STATUS_FAILED
+/* Optional feature of NCI Spec not supported */
+#define NFA_STATUS_NOT_SUPPORTED NCI_STATUS_NOT_SUPPORTED
 /* Semantic error       */
 #define NFA_STATUS_SEMANTIC_ERROR NCI_STATUS_SEMANTIC_ERROR
 /* Unknown NCI Group ID */
diff --git a/src/nfa/include/nfa_ee_api.h b/src/nfa/include/nfa_ee_api.h
index 342fe29..7df0df4 100644
--- a/src/nfa/include/nfa_ee_api.h
+++ b/src/nfa/include/nfa_ee_api.h
@@ -41,9 +41,13 @@
   NFA_EE_DEREGISTER_EVT, /* The status for NFA_EeDeregister () */
   NFA_EE_MODE_SET_EVT, /* The status for activating or deactivating an NFCEE */
   NFA_EE_ADD_AID_EVT,  /* The status for adding an AID to a routing table entry
-                          */
-  NFA_EE_REMOVE_AID_EVT, /* The status for removing an AID from a routing table
-                            */
+                        */
+  NFA_EE_REMOVE_AID_EVT,  /* The status for removing an AID from a routing table
+                           */
+  NFA_EE_ADD_SYSCODE_EVT, /* The status for adding an System Code to a routing
+                             table entry */
+  NFA_EE_REMOVE_SYSCODE_EVT, /* The status for removing an System Code from
+                              routing table */
   NFA_EE_REMAINING_SIZE_EVT, /* The remaining size of the Listen Mode Routing
                                 Table   */
   NFA_EE_SET_TECH_CFG_EVT,   /* The status for setting the routing based on RF
@@ -183,6 +187,8 @@
   tNFA_STATUS deregister;
   tNFA_STATUS add_aid;
   tNFA_STATUS remove_aid;
+  tNFA_STATUS add_sc;
+  tNFA_STATUS remove_sc;
   tNFA_STATUS set_tech;
   tNFA_STATUS set_proto;
   uint16_t size;
@@ -377,6 +383,54 @@
 extern tNFA_STATUS NFA_EeRemoveAidRouting(uint8_t aid_len, uint8_t* p_aid);
 
 /*******************************************************************************
+ **
+ ** Function         NFA_EeAddSystemCodeRouting
+ **
+ ** Description      This function is called to add an system code entry in the
+ **                  listen mode routing table in NFCC. The status of this
+ **                  operation is reported as the NFA_EE_ADD_SYSCODE_EVT.
+ **
+ ** Note:            If RF discovery is started,
+ **                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
+ **                  happen before calling this function
+ **
+ ** Note:            NFA_EeUpdateNow() should be called after last NFA-EE
+ **                  function to change the listen mode routing is called.
+ **
+ ** Returns          NFA_STATUS_OK if successfully initiated
+ **                  NFA_STATUS_FAILED otherwise
+ **                  NFA_STATUS_INVALID_PARAM If bad parameter
+ **
+ *******************************************************************************/
+extern tNFA_STATUS NFA_EeAddSystemCodeRouting(uint16_t systemcode,
+                                              tNFA_HANDLE ee_handle,
+                                              tNFA_EE_PWR_STATE power_state);
+
+/*******************************************************************************
+**
+** Function         NFA_EeRemoveSystemCodeRouting
+**
+** Description      This function is called to remove the given System Code
+*based entry from
+**                  the listen mode routing table. The status of this operation
+*is reported
+**                  as the NFA_EE_REMOVE_SYSCODE_EVT.
+**
+** Note:            If RF discovery is started,
+**                  NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT should
+**                  happen before calling this function
+**
+** Note:            NFA_EeUpdateNow() should be called after last NFA-EE
+**                  function to change the listen mode routing is called.
+**
+** Returns          NFA_STATUS_OK if successfully initiated
+**                  NFA_STATUS_FAILED otherwise
+**                  NFA_STATUS_INVALID_PARAM If bad parameter
+**
+*******************************************************************************/
+extern tNFA_STATUS NFA_EeRemoveSystemCodeRouting(uint16_t systemcode);
+
+/*******************************************************************************
 **
 ** Function         NFA_EeGetLmrtRemainingSize
 **
diff --git a/src/nfa/include/nfa_ee_int.h b/src/nfa/include/nfa_ee_int.h
index 5730ad7..c700027 100644
--- a/src/nfa/include/nfa_ee_int.h
+++ b/src/nfa/include/nfa_ee_int.h
@@ -53,6 +53,8 @@
   NFA_EE_API_SET_PROTO_CFG_EVT,
   NFA_EE_API_ADD_AID_EVT,
   NFA_EE_API_REMOVE_AID_EVT,
+  NFA_EE_API_ADD_SYSCODE_EVT,
+  NFA_EE_API_REMOVE_SYSCODE_EVT,
   NFA_EE_API_LMRT_SIZE_EVT,
   NFA_EE_API_UPDATE_NOW_EVT,
   NFA_EE_API_CONNECT_EVT,
@@ -103,6 +105,12 @@
 
 #define NFA_EE_MAX_AID_CFG_LEN (510)
 
+#define NFA_EE_SYSTEM_CODE_LEN 02
+#define NFA_EE_SYSTEM_CODE_TLV_SIZE 06
+#define NFA_EE_MAX_SYSTEM_CODE_ENTRIES 10
+#define NFA_EE_MAX_SYSTEM_CODE_CFG_LEN \
+  (NFA_EE_MAX_SYSTEM_CODE_ENTRIES * NFA_EE_SYSTEM_CODE_TLV_SIZE)
+
 /* NFA EE control block flags:
  * use to indicate an API function has changed the configuration of the
  * associated NFCEE
@@ -113,6 +121,8 @@
 #define NFA_EE_ECB_FLAGS_PROTO 0x04
 /* AID routing changed                */
 #define NFA_EE_ECB_FLAGS_AID 0x08
+/* System Code routing changed        */
+#define NFA_EE_ECB_FLAGS_SYSCODE 0xE0
 /* VS changed                         */
 #define NFA_EE_ECB_FLAGS_VS 0x10
 /* Restore related                    */
@@ -181,6 +191,14 @@
   uint8_t size_mask; /* the size for technology and protocol routing */
   uint16_t size_aid; /* the size for aid routing */
   uint8_t aid_info[NFA_EE_MAX_AID_ENTRIES]; /* Aid Info Prefix/Suffix/Exact */
+  /*System Code Based Routing Variables*/
+  uint8_t sys_code_cfg[NFA_EE_MAX_SYSTEM_CODE_ENTRIES * NFA_EE_SYSTEM_CODE_LEN];
+  uint8_t sys_code_pwr_cfg[NFA_EE_MAX_SYSTEM_CODE_ENTRIES];
+  uint8_t sys_code_rt_loc[NFA_EE_MAX_SYSTEM_CODE_ENTRIES];
+  uint8_t sys_code_rt_loc_vs_info[NFA_EE_MAX_SYSTEM_CODE_ENTRIES];
+  /* The number of SC entries in sys_code_cfg buffer*/
+  uint8_t sys_code_cfg_entries;
+  uint16_t size_sys_code; /* The size for system code routing */
 } tNFA_EE_ECB;
 
 /* data type for NFA_EE_API_DISCOVER_EVT */
@@ -247,6 +265,21 @@
   uint8_t* p_aid;
 } tNFA_EE_API_REMOVE_AID;
 
+/* data type for NFA_EE_API_ADD_SYSCODE_EVT */
+typedef struct {
+  NFC_HDR hdr;
+  tNFA_EE_ECB* p_cb;
+  uint8_t nfcee_id;
+  uint16_t syscode;
+  tNFA_EE_PWR_STATE power_state;
+} tNFA_EE_API_ADD_SYSCODE;
+
+/* data type for NFA_EE_API_REMOVE_SYSCODE_EVT */
+typedef struct {
+  NFC_HDR hdr;
+  uint16_t syscode;
+} tNFA_EE_API_REMOVE_SYSCODE;
+
 /* data type for NFA_EE_API_LMRT_SIZE_EVT */
 typedef NFC_HDR tNFA_EE_API_LMRT_SIZE;
 
@@ -339,6 +372,8 @@
   tNFA_EE_API_SET_PROTO_CFG set_proto;
   tNFA_EE_API_ADD_AID add_aid;
   tNFA_EE_API_REMOVE_AID rm_aid;
+  tNFA_EE_API_ADD_SYSCODE add_syscode;
+  tNFA_EE_API_REMOVE_SYSCODE rm_syscode;
   tNFA_EE_API_LMRT_SIZE lmrt_size;
   tNFA_EE_API_CONNECT connect;
   tNFA_EE_API_SEND_DATA send_data;
@@ -420,6 +455,7 @@
 
 /* Order of Routing entries in Routing Table */
 #define NCI_ROUTE_ORDER_AID 0x01        /* AID routing order */
+#define NCI_ROUTE_ORDER_SYS_CODE 0x03   /* System Code routing order*/
 #define NCI_ROUTE_ORDER_PROTOCOL 0x04   /* Protocol routing order*/
 #define NCI_ROUTE_ORDER_TECHNOLOGY 0x05 /* Technology routing order*/
 
@@ -459,6 +495,8 @@
 void nfa_ee_api_set_proto_cfg(tNFA_EE_MSG* p_data);
 void nfa_ee_api_add_aid(tNFA_EE_MSG* p_data);
 void nfa_ee_api_remove_aid(tNFA_EE_MSG* p_data);
+void nfa_ee_api_add_sys_code(tNFA_EE_MSG* p_data);
+void nfa_ee_api_remove_sys_code(tNFA_EE_MSG* p_data);
 void nfa_ee_api_lmrt_size(tNFA_EE_MSG* p_data);
 void nfa_ee_api_update_now(tNFA_EE_MSG* p_data);
 void nfa_ee_api_connect(tNFA_EE_MSG* p_data);
@@ -480,7 +518,8 @@
                          tNFA_EE_CBACK_DATA* p_data);
 tNFA_EE_ECB* nfa_ee_find_aid_offset(uint8_t aid_len, uint8_t* p_aid,
                                     int* p_offset, int* p_entry);
-
+tNFA_EE_ECB* nfa_ee_find_sys_code_offset(uint16_t sys_code, int* p_offset,
+                                         int* p_entry);
 int nfa_ee_find_total_aid_len(tNFA_EE_ECB* p_cb, int start_entry);
 void nfa_ee_start_timer(void);
 void nfa_ee_reg_cback_enable_done(tNFA_EE_ENABLE_DONE_CBACK* p_cback);
diff --git a/src/nfc/include/nfc_api.h b/src/nfc/include/nfc_api.h
index b43a97f..3601867 100644
--- a/src/nfc/include/nfc_api.h
+++ b/src/nfc/include/nfc_api.h
@@ -142,6 +142,7 @@
 /* Protocol based routing  */
 #define NFC_ROUTE_TAG_PROTO NCI_ROUTE_TAG_PROTO
 #define NFC_ROUTE_TAG_AID NCI_ROUTE_TAG_AID /* AID routing */
+#define NFC_ROUTE_TAG_SYSCODE NCI_ROUTE_TAG_SYSCODE /* System Code routing*/
 /* tag, len, 2 byte value for technology/protocol based routing */
 
 /* For routing */
diff --git a/src/nfc/include/nfc_int.h b/src/nfc/include/nfc_int.h
index 592b23d..71b8564 100644
--- a/src/nfc/include/nfc_int.h
+++ b/src/nfc/include/nfc_int.h
@@ -214,6 +214,8 @@
 
   uint8_t nci_version; /* NCI version used for NCI communication*/
 
+  bool isScbrSupported; /* indicating if system code based route is supported */
+
   uint8_t hci_packet_size; /* maximum hci payload size*/
 
   uint8_t hci_conn_credits; /* maximum conn credits for static HCI*/
diff --git a/src/nfc/nfc/nfc_ncif.cc b/src/nfc/nfc/nfc_ncif.cc
index 9b800c6..42aad5c 100644
--- a/src/nfc/nfc/nfc_ncif.cc
+++ b/src/nfc/nfc/nfc_ncif.cc
@@ -1395,6 +1395,10 @@
       nci_snd_core_reset(NCI_RESET_TYPE_RESET_CFG);
     } else {
       p_cb->id = NFC_RF_CONN_ID;
+      // check scbr bit as per NCI 2.0 spec
+      nfc_cb.isScbrSupported = p[5] & NCI_SCBR_MASK;
+      DLOG_IF(INFO, nfc_debug_enabled)
+          << StringPrintf("scbr support: 0x%x", nfc_cb.isScbrSupported);
       p_cb->act_protocol = NCI_PROTOCOL_UNKNOWN;
 
       nfc_set_state(NFC_STATE_W4_POST_INIT_CPLT);