Set power level to 0 when stack shuts down

The last command during stack shutdown is setting controller's power
level to 0 to prevent the controller from using any battery power.

Change-Id: I971267ee3b861c5d6bc9a1dc032fd8e991b15304
diff --git a/halimpl/bcm2079x/hal/hal/nfc_hal_dm.c b/halimpl/bcm2079x/hal/hal/nfc_hal_dm.c
index 9e200f8..58674ed 100644
--- a/halimpl/bcm2079x/hal/hal/nfc_hal_dm.c
+++ b/halimpl/bcm2079x/hal/hal/nfc_hal_dm.c
@@ -431,6 +431,31 @@
 
 /*******************************************************************************
 **
+** Function         nfc_hal_dm_set_power_level_zero
+**
+** Description      set power level to 0
+**
+** Returns          None
+**
+*******************************************************************************/
+void nfc_hal_dm_set_power_level_zero (void)
+{
+    UINT8 nci_brcm_set_pwr_level_cmd[NCI_MSG_HDR_SIZE + NCI_PARAM_LEN_POWER_LEVEL];
+    UINT8 *p;
+    UINT8 cmd_len = NCI_PARAM_LEN_POWER_LEVEL;
+
+    p = nci_brcm_set_pwr_level_cmd;
+    UINT8_TO_STREAM  (p, (NCI_MTS_CMD|NCI_GID_PROP));
+    UINT8_TO_STREAM  (p, NCI_MSG_POWER_LEVEL);
+    UINT8_TO_STREAM  (p, NCI_PARAM_LEN_POWER_LEVEL);
+    memset (p, 0, NCI_PARAM_LEN_POWER_LEVEL);
+
+    nfc_hal_dm_send_nci_cmd (nci_brcm_set_pwr_level_cmd, NCI_MSG_HDR_SIZE + cmd_len,
+                             nfc_hal_main_exit_op_done);
+}
+
+/*******************************************************************************
+**
 ** Function         nfc_hal_dm_send_get_build_info_cmd
 **
 ** Description      Send NCI_MSG_GET_BUILD_INFO CMD
@@ -562,6 +587,25 @@
 
 /*******************************************************************************
 **
+** Function         nfc_hal_dm_got_vs_rsp
+**
+** Description      Received VS RSP. Clean up control block to allow next NCI cmd
+**
+** Returns          void
+**
+*******************************************************************************/
+tNFC_HAL_NCI_CBACK * nfc_hal_dm_got_vs_rsp (void)
+{
+    tNFC_HAL_NCI_CBACK *p_cback = NULL;
+    nfc_hal_cb.ncit_cb.nci_wait_rsp = NFC_HAL_WAIT_RSP_NONE;
+    p_cback = (tNFC_HAL_NCI_CBACK *)nfc_hal_cb.ncit_cb.p_vsc_cback;
+    nfc_hal_cb.ncit_cb.p_vsc_cback  = NULL;
+    nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer);
+    return p_cback;
+}
+
+/*******************************************************************************
+**
 ** Function         nfc_hal_dm_proc_msg_during_init
 **
 ** Description      Process NCI message while initializing NFCC
@@ -675,6 +719,13 @@
 
             STREAM_TO_ARRAY (chipverstr, p, chipverlen);
 
+            /* If chip is not 20791 and 43341, set flag to send the "Disable" VSC */
+            if ( ((nfc_hal_cb.dev_cb.brcm_hw_id & BRCM_NFC_GEN_MASK) != BRCM_NFC_20791_GEN)
+                && ((nfc_hal_cb.dev_cb.brcm_hw_id & BRCM_NFC_GEN_MASK) != BRCM_NFC_43341_GEN) )
+            {
+                nfc_hal_cb.hal_flags |= NFC_HAL_FLAGS_NEED_DISABLE_VSC;
+            }
+
             nfc_hal_hci_handle_build_info (chipverlen, chipverstr);
             nfc_hal_cb.pre_set_mem_idx = 0;
             if (!nfc_hal_dm_check_pre_set_mem())
@@ -769,6 +820,67 @@
 
 /*******************************************************************************
 **
+** Function         nfc_hal_dm_proc_msg_during_exit
+**
+** Description      Process NCI message while shutting down NFCC
+**
+** Returns          void
+**
+*******************************************************************************/
+void nfc_hal_dm_proc_msg_during_exit (NFC_HDR *p_msg)
+{
+    UINT8 *p;
+    UINT8 mt, pbf, gid, op_code;
+    UINT8 *p_old, old_gid, old_oid, old_mt;
+    UINT8 u8;
+    tNFC_HAL_NCI_CBACK *p_cback = NULL;
+
+    HAL_TRACE_DEBUG1 ("nfc_hal_dm_proc_msg_during_exit(): state:%d", nfc_hal_cb.dev_cb.initializing_state);
+
+    p = (UINT8 *) (p_msg + 1) + p_msg->offset;
+
+    NCI_MSG_PRS_HDR0 (p, mt, pbf, gid);
+    NCI_MSG_PRS_HDR1 (p, op_code);
+    u8  = *p;
+
+    /* check if waiting for this response */
+    if (  (nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_CMD)
+        ||(nfc_hal_cb.ncit_cb.nci_wait_rsp == NFC_HAL_WAIT_RSP_VSC)  )
+    {
+        if (mt == NCI_MT_RSP)
+        {
+            p_old = nfc_hal_cb.ncit_cb.last_hdr;
+            NCI_MSG_PRS_HDR0 (p_old, old_mt, pbf, old_gid);
+            old_oid = ((*p_old) & NCI_OID_MASK);
+            /* make sure this is the RSP we are waiting for before updating the command window */
+            if ((old_gid == gid) && (old_oid == op_code))
+            {
+                p_cback = nfc_hal_dm_got_vs_rsp ();
+                if (p_cback)
+                {
+                    if (gid == NCI_GID_PROP)
+                    {
+                        if (mt == NCI_MT_NTF)
+                            op_code |= NCI_NTF_BIT;
+                        else
+                            op_code |= NCI_RSP_BIT;
+
+                        if (op_code == NFC_VS_POWER_LEVEL_RSP)
+                        {
+                            (*p_cback) ((tNFC_HAL_NCI_EVT) (op_code),
+                                        p_msg->len,
+                                        (UINT8 *) (p_msg + 1) + p_msg->offset);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+}
+
+/*******************************************************************************
+**
 ** Function         nfc_hal_dm_send_nci_cmd
 **
 ** Description      Send NCI command to NFCC while initializing BRCM NFCC
diff --git a/halimpl/bcm2079x/hal/hal/nfc_hal_main.c b/halimpl/bcm2079x/hal/hal/nfc_hal_main.c
index d7fc5d5..c353b5f 100644
--- a/halimpl/bcm2079x/hal/hal/nfc_hal_main.c
+++ b/halimpl/bcm2079x/hal/hal/nfc_hal_main.c
@@ -131,6 +131,41 @@
 
 /*******************************************************************************
 **
+** Function         nfc_hal_main_close
+**
+** Description      Check and shutdown NFCC
+**
+** Returns          None
+**
+*******************************************************************************/
+void nfc_hal_main_close (void)
+{
+    tHAL_NFC_CBACK *p_stack_cback_temp;
+
+    if (  (nfc_hal_cb.dev_cb.initializing_state != NFC_HAL_INIT_STATE_W4_NFCC_TURN_OFF)
+        && (nfc_hal_cb.hal_flags & NFC_HAL_FLAGS_NEED_DISABLE_VSC) )
+    {
+        nfc_hal_cb.dev_cb.initializing_state = NFC_HAL_INIT_STATE_W4_NFCC_TURN_OFF;
+        nfc_hal_dm_set_power_level_zero ();
+    }
+    else
+    {
+        nfc_hal_main_handle_terminate ();
+
+        /* Close uart */
+        USERIAL_Close (USERIAL_NFC_PORT);
+
+        if (nfc_hal_cb.p_stack_cback)
+        {
+            p_stack_cback_temp          = nfc_hal_cb.p_stack_cback;
+            nfc_hal_cb.p_stack_cback    = NULL;
+            p_stack_cback_temp (HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK);
+        }
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         nfa_hal_pre_discover_done_cback
 **
 ** Description      Pre-discovery CFG is sent.
@@ -225,6 +260,20 @@
 
 /*******************************************************************************
 **
+** Function         nfc_hal_main_exit_op_done
+**
+** Description      handle completion of HAL exit operation
+**
+** Returns          nothing
+**
+*******************************************************************************/
+void nfc_hal_main_exit_op_done (tNFC_HAL_NCI_EVT event, UINT16 data_len, UINT8 *p_data)
+{
+    nfc_hal_main_close ();
+}
+
+/*******************************************************************************
+**
 ** Function         nfc_hal_main_pre_init_done
 **
 ** Description      notify complete of pre-initialization
@@ -602,16 +651,9 @@
         if (event & NFC_HAL_TASK_EVT_TERMINATE)
         {
             HAL_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_TERMINATE");
-            nfc_hal_main_handle_terminate ();
 
-            /* Close uart */
-            USERIAL_Close (USERIAL_NFC_PORT);
+            nfc_hal_main_close ();
 
-            if (nfc_hal_cb.p_stack_cback)
-            {
-                nfc_hal_cb.p_stack_cback (HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK);
-                nfc_hal_cb.p_stack_cback = NULL;
-            }
             continue;
         }
 
diff --git a/halimpl/bcm2079x/hal/hal/nfc_hal_nci.c b/halimpl/bcm2079x/hal/hal/nfc_hal_nci.c
index f4eb9af..d60a945 100644
--- a/halimpl/bcm2079x/hal/hal/nfc_hal_nci.c
+++ b/halimpl/bcm2079x/hal/hal/nfc_hal_nci.c
@@ -535,6 +535,14 @@
 
     HAL_TRACE_DEBUG0 ("nfc_hal_nci_preproc_rx_nci_msg()");
 
+    if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_NFCC_TURN_OFF)
+    {
+        /* if turning off BRCM NFCC */
+        nfc_hal_dm_proc_msg_during_exit (p_msg);
+        /* do not send message to NFC task while shutting down */
+        return (FALSE);
+    }
+
     /* if initializing BRCM NFCC */
     if (nfc_hal_cb.dev_cb.initializing_state != NFC_HAL_INIT_STATE_IDLE)
     {
@@ -866,6 +874,10 @@
             NFC_HAL_SET_INIT_STATE(NFC_HAL_INIT_STATE_IDLE);
             nfc_hal_cb.p_stack_cback (HAL_NFC_PRE_DISCOVER_CPLT_EVT, HAL_NFC_STATUS_ERR_CMD_TIMEOUT);
         }
+        else if (nfc_hal_cb.dev_cb.initializing_state == NFC_HAL_INIT_STATE_W4_NFCC_TURN_OFF)
+        {
+            nfc_hal_main_close ();
+        }
     }
 }
 
diff --git a/src/hal/int/nfc_brcm_defs.h b/src/hal/int/nfc_brcm_defs.h
index ff242f5..2e2f252 100644
--- a/src/hal/int/nfc_brcm_defs.h
+++ b/src/hal/int/nfc_brcm_defs.h
@@ -253,6 +253,7 @@
 #define NCI_PARAM_LEN_PWR_SETTING_BITMAP    3
 #define NCI_PARAM_LEN_HOST_LISTEN_MASK      2
 #define NCI_PARAM_LEN_PLL325_CFG_PARAM      14
+#define NCI_PARAM_LEN_POWER_LEVEL           6
 
 /**********************************************
  * Snooze Mode
diff --git a/src/hal/int/nfc_hal_int.h b/src/hal/int/nfc_hal_int.h
index fbde0f9..d4f0272 100644
--- a/src/hal/int/nfc_hal_int.h
+++ b/src/hal/int/nfc_hal_int.h
@@ -217,6 +217,7 @@
     NFC_HAL_INIT_STATE_W4_POST_INIT_DONE,  /* Waiting for complete of post init     */
     NFC_HAL_INIT_STATE_W4_CONTROL_DONE,    /* Waiting for control release           */
     NFC_HAL_INIT_STATE_W4_PREDISCOVER_DONE,/* Waiting for complete of prediscover   */
+    NFC_HAL_INIT_STATE_W4_NFCC_TURN_OFF,   /* Waiting for NFCC to turn OFF          */
     NFC_HAL_INIT_STATE_CLOSING             /* Shutting down                         */
 };
 typedef UINT8 tNFC_HAL_INIT_STATE;
@@ -412,6 +413,9 @@
 
 #endif
 
+#define NFC_HAL_FLAGS_NEED_DISABLE_VSC  0x01
+typedef UINT8 tNFC_HAL_FLAGS;
+
 typedef struct
 {
     tHAL_NFC_CBACK          *p_stack_cback;     /* Callback for HAL event notification  */
@@ -434,6 +438,7 @@
 #endif
 
     UINT8                   pre_discover_done;  /* TRUE, when the prediscover config is complete */
+    tNFC_HAL_FLAGS          hal_flags;
     UINT8                   pre_set_mem_idx;
 
     UINT8                   max_rf_credits;     /* NFC Max RF data credits */
@@ -456,7 +461,9 @@
 /* From nfc_hal_main.c */
 UINT32 nfc_hal_main_task (UINT32 param);
 void   nfc_hal_main_init (void);
+void   nfc_hal_main_close (void);
 void   nfc_hal_main_pre_init_done (tHAL_NFC_STATUS);
+void   nfc_hal_main_exit_op_done (tNFC_HAL_NCI_EVT event, UINT16 data_len, UINT8 *p_data);
 void   nfc_hal_main_start_quick_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout);
 void   nfc_hal_main_stop_quick_timer (TIMER_LIST_ENT *p_tle);
 void   nfc_hal_main_send_error (tHAL_NFC_STATUS status);
@@ -474,8 +481,10 @@
 /* nfc_hal_dm.c */
 void nfc_hal_dm_init (void);
 void nfc_hal_dm_set_xtal_freq_index (void);
+void nfc_hal_dm_set_power_level_zero (void);
 void nfc_hal_dm_send_get_build_info_cmd (void);
 void nfc_hal_dm_proc_msg_during_init (NFC_HDR *p_msg);
+void nfc_hal_dm_proc_msg_during_exit (NFC_HDR *p_msg);
 void nfc_hal_dm_config_nfcc (void);
 void nfc_hal_dm_send_nci_cmd (const UINT8 *p_data, UINT16 len, tNFC_HAL_NCI_CBACK *p_cback);
 void nfc_hal_dm_send_bt_cmd (const UINT8 *p_data, UINT16 len, tNFC_HAL_BTVSC_CPLT_CBACK *p_cback);
@@ -486,6 +495,7 @@
 void nfc_hal_dm_send_pend_cmd (void);
 tHAL_NFC_STATUS nfc_hal_dm_set_config (UINT8 tlv_size, UINT8 *p_param_tlvs, tNFC_HAL_NCI_CBACK *p_cback);
 BOOLEAN nfc_hal_dm_check_pre_set_mem (void);
+tNFC_HAL_NCI_CBACK * nfc_hal_dm_got_vs_rsp (void);
 
 
 /* nfc_hal_prm.c */