Add support of getting factory BDADDR from Controller's non-volatile memory(2/2)

When factory Bluetooth device address is stored in the BT Controller's
non-volatile memory (e.g. BCM4330 OTP memory) instead of devices's file system,
the BDADDR will be retrieved from the Controller while enabling Bluedroid core
stack.

Introduce USE_CONTROLLER_BDADDR preprocessor directive in the vendor lib.

After patchram download, check whether the BT Controller has a non-zero's BDADDR
stored in its non-volatile memory. If not, write BTIF's init BDADDR to the
Controller.

bug 7340441

Change-Id: I2414b9479d4ef93ffd20c7ccc4875aab009e7cc8
diff --git a/libbt/include/bt_vendor_brcm.h b/libbt/include/bt_vendor_brcm.h
index 2ecc21e..fff1925 100644
--- a/libbt/include/bt_vendor_brcm.h
+++ b/libbt/include/bt_vendor_brcm.h
@@ -82,6 +82,24 @@
 #define FW_PATCH_SETTLEMENT_DELAY_MS          0
 #endif
 
+/* The Bluetooth Device Aaddress source switch:
+ *
+ * -FALSE- (default value)
+ *  Get the factory BDADDR from device's file system. Normally the BDADDR is
+ *  stored in the location pointed by the PROPERTY_BT_BDADDR_PATH (defined in
+ *  btif_common.h file) property.
+ *
+ * -TRUE-
+ *  If the Bluetooth Controller has equipped with a non-volatile memory (such
+ *  as BCM4330's OTP memory), the factory BDADDR can be stored in there and
+ *  retrieved by the stack while enabling BT.
+ *  !!! WARNING !!! Make sure that the OTP feature has been enabled in the
+ *  firmware patchram (.hcd) file.
+ */
+#ifndef USE_CONTROLLER_BDADDR
+#define USE_CONTROLLER_BDADDR   FALSE
+#endif
+
 /* sleep mode
 
     0: disable
diff --git a/libbt/include/vnd_grouper.txt b/libbt/include/vnd_grouper.txt
index 3667e65..65ef840 100755
--- a/libbt/include/vnd_grouper.txt
+++ b/libbt/include/vnd_grouper.txt
@@ -7,3 +7,4 @@
 VNDUSERIAL_DBG = FALSE
 UPIO_DBG = FALSE
 SCO_PCM_IF_CLOCK_RATE = 2
+USE_CONTROLLER_BDADDR = TRUE
diff --git a/libbt/include/vnd_tilapia.txt b/libbt/include/vnd_tilapia.txt
index 3667e65..65ef840 100755
--- a/libbt/include/vnd_tilapia.txt
+++ b/libbt/include/vnd_tilapia.txt
@@ -7,3 +7,4 @@
 VNDUSERIAL_DBG = FALSE
 UPIO_DBG = FALSE
 SCO_PCM_IF_CLOCK_RATE = 2
+USE_CONTROLLER_BDADDR = TRUE
diff --git a/libbt/src/hardware.c b/libbt/src/hardware.c
index a6868e1..397507d 100644
--- a/libbt/src/hardware.c
+++ b/libbt/src/hardware.c
@@ -77,9 +77,11 @@
 #define HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM     0xFC1E
 #define HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM    0xFC6D
 #define HCI_VSC_LAUNCH_RAM                      0xFC4E
+#define HCI_READ_LOCAL_BDADDR                   0x1009
 
 #define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE        5
 #define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING      6
+#define HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY     6
 #define HCI_EVT_CMD_CMPL_OPCODE                 3
 #define LPM_CMD_PARAM_SIZE                      12
 #define UPDATE_BAUDRATE_CMD_PARAM_SIZE          6
@@ -107,6 +109,9 @@
     HW_CFG_DL_FW_PATCH,
     HW_CFG_SET_UART_BAUD_2,
     HW_CFG_SET_BD_ADDR
+#if (USE_CONTROLLER_BDADDR == TRUE)
+    , HW_CFG_READ_BD_ADDR
+#endif
 };
 
 /* h/w config control block */
@@ -534,6 +539,35 @@
     return (retval);
 }
 
+#if (USE_CONTROLLER_BDADDR == TRUE)
+/*******************************************************************************
+**
+** Function         hw_config_read_bdaddr
+**
+** Description      Read controller's Bluetooth Device Address
+**
+** Returns          TRUE, if valid address is sent
+**                  FALSE, otherwise
+**
+*******************************************************************************/
+static uint8_t hw_config_read_bdaddr(HC_BT_HDR *p_buf)
+{
+    uint8_t retval = FALSE;
+    uint8_t *p = (uint8_t *) (p_buf + 1);
+
+    UINT16_TO_STREAM(p, HCI_READ_LOCAL_BDADDR);
+    *p = 0; /* parameter length */
+
+    p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+    hw_cfg_cb.state = HW_CFG_READ_BD_ADDR;
+
+    retval = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_BDADDR, p_buf, \
+                                 hw_config_cback);
+
+    return (retval);
+}
+#endif // (USE_CONTROLLER_BDADDR == TRUE)
+
 /*******************************************************************************
 **
 ** Function         hw_config_cback
@@ -552,6 +586,9 @@
     HC_BT_HDR  *p_buf=NULL;
     uint8_t     is_proceeding = FALSE;
     int         i;
+#if (USE_CONTROLLER_BDADDR == TRUE)
+    const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
+#endif
 
     status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
     p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
@@ -735,9 +772,13 @@
                     line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \
                 );
 
+#if (USE_CONTROLLER_BDADDR == TRUE)
+                if ((is_proceeding = hw_config_read_bdaddr(p_buf)) == TRUE)
+                    break;
+#else
                 if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
                     break;
-
+#endif
                 /* fall through intentionally */
             case HW_CFG_SET_BD_ADDR:
                 ALOGI("vendor lib fwcfg completed");
@@ -754,6 +795,41 @@
 
                 is_proceeding = TRUE;
                 break;
+
+#if (USE_CONTROLLER_BDADDR == TRUE)
+            case HW_CFG_READ_BD_ADDR:
+                p_tmp = (char *) (p_evt_buf + 1) + \
+                         HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY;
+
+                if (memcmp(p_tmp, null_bdaddr, BD_ADDR_LEN) == 0)
+                {
+                    // Controller does not have a valid OTP BDADDR!
+                    // Set the BTIF initial BDADDR instead.
+                    if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
+                        break;
+                }
+                else
+                {
+                    ALOGI("Controller OTP bdaddr %02X:%02X:%02X:%02X:%02X:%02X",
+                        *(p_tmp+5), *(p_tmp+4), *(p_tmp+3),
+                        *(p_tmp+2), *(p_tmp+1), *p_tmp);
+                }
+
+                ALOGI("vendor lib fwcfg completed");
+                bt_vendor_cbacks->dealloc(p_buf);
+                bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+
+                hw_cfg_cb.state = 0;
+
+                if (hw_cfg_cb.fw_fd != -1)
+                {
+                    close(hw_cfg_cb.fw_fd);
+                    hw_cfg_cb.fw_fd = -1;
+                }
+
+                is_proceeding = TRUE;
+                break;
+#endif // (USE_CONTROLLER_BDADDR == TRUE)
         } // switch(hw_cfg_cb.state)
     } // if (p_buf != NULL)