Add vendor support for FM Sub-system in the WCNSS HAL layer.

FM will be sharing the underlying transport layer with BT and ANT for
sending/receiving cmds/events.Hence, add FM vendor operations such as FM ON,
OFF and obtaining FM Client Socket handle for sending and receiving
commands/events between the APPS proc and Helium chipset, into libbt-vendor.so
shared library. Currently this library has support for BT and ANT
vendor operations. Moving on, add FM vendor specific operations
into the libbt-vendor.so library and rename it as WCNSS HAL layer.

Change-Id: I0f3123456822033a17f0b9ba59559f735d4c4717
diff --git a/libbt-vendor/src/bt_vendor_qcom.c b/libbt-vendor/src/bt_vendor_qcom.c
index cd579c5..09cd32c 100644
--- a/libbt-vendor/src/bt_vendor_qcom.c
+++ b/libbt-vendor/src/bt_vendor_qcom.c
@@ -40,7 +40,7 @@
 #include "hw_rome.h"
 #include "bt_vendor_lib.h"
 #define WAIT_TIMEOUT 200000
-#define BT_VND_OP_GET_LINESPEED 12
+#define BT_VND_OP_GET_LINESPEED 30
 
 #ifdef PANIC_ON_SOC_CRASH
 #define BT_VND_FILTER_START "wc_transport.start_root"
@@ -50,7 +50,7 @@
 
 #define CMD_TIMEOUT  0x22
 
-static void wait_for_patch_download(bool is_ant_req);
+static void wait_for_patch_download(bool is_ant_fm_req);
 static bool is_debug_force_special_bytes(void);
 
 /******************************************************************************
@@ -71,6 +71,7 @@
 int pFd[2] = {0,};
 #if (BT_SOC_TYPE_ROME ||BT_SOC_TYPE_CHEROKEE)
 int ant_fd;
+int fm_fd;
 #endif
 bt_vendor_callbacks_t *bt_vendor_cbacks = NULL;
 uint8_t vnd_local_bd_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
@@ -269,8 +270,8 @@
         }
 
         if (value == 1)
-           can_perform = true;
-        else if (value > 2)
+            can_perform = true;
+        else if (value > 3)
            return false;
     }
     else {
@@ -542,8 +543,11 @@
         case BT_SOC_CHEROKEE:
         case BT_SOC_ROME:
         case BT_SOC_AR3K:
-            ALOGI("bt-vendor : Initializing UART transport layer");
-            userial_vendor_init();
+            ALOGI("bt-vendor : check soc initialized ");
+            if (!is_soc_initialized()) {
+                ALOGI("bt-vendor : Initializing UART transport layer");
+                userial_vendor_init();
+            }
             break;
         case BT_SOC_DEFAULT:
             break;
@@ -652,6 +656,7 @@
     int nCnt = 0;
     int nState = -1;
     bool is_ant_req = false;
+    bool is_fm_req = false;
     char wipower_status[PROPERTY_VALUE_MAX];
     char emb_wp_mode[PROPERTY_VALUE_MAX];
     char bt_version[PROPERTY_VALUE_MAX];
@@ -668,6 +673,14 @@
 
     switch(opcode_init)
     {
+        case FM_VND_OP_POWER_CTRL:
+            {
+              is_fm_req = true;
+              if (is_soc_initialized()) {
+                  // add any FM specific actions  if needed in future
+                  break;
+              }
+            }
         case BT_VND_OP_POWER_CTRL:
             {
                 nState = *(int *) param;
@@ -740,9 +753,14 @@
         case BT_VND_OP_ANT_USERIAL_OPEN:
                 ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_OPEN");
                 is_ant_req = true;
-                //fall through
+                goto userial_open;
 #endif
 #endif
+        case BT_VND_OP_FM_USERIAL_OPEN:
+                ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_OPEN");
+                is_fm_req = true;
+                goto userial_open;
+userial_open:
         case BT_VND_OP_USERIAL_OPEN:
             {
                 int (*fd_array)[] = (int (*)[]) param;
@@ -791,42 +809,45 @@
                     case BT_SOC_CHEROKEE:
                         {
                             /* Cherokee need to wake up first through UART Tx line */
-                            int len;
-                            char reset_val = 0xFC;
-                            fd = userial_vendor_open((tUSERIAL_CFG *) &bt_reset_cfg);
-                            if (fd < 0) {
-                                ALOGE("userial_vendor_open returns err");
-                                retval = -1;
-                            } else {
-                                /* Clock on */
-                                userial_clock_operation(fd, USERIAL_OP_CLK_ON);
-                                ALOGD("userial clock on");
-
-                                /* Give some delay before clock and uart driver is ramping up and ready */
-                                usleep(200); /* 200 us delay */
-
-                                /* UART TxD control as BT Reset*/
-                                /* 0xFC = 3 bits = 8.6 us *3 =  25.8us */
-                                len = write(fd, &reset_val, 1);
-                                if (len != 1 ) {
-                                    ALOGE("%s: Send failed with ret value: %d", __FUNCTION__, len);
+                            if (!is_soc_initialized()) {
+                                wait_for_patch_download(is_ant_req | is_fm_req);
+                                int len;
+                                char reset_val = 0xFC;
+                                fd = userial_vendor_open((tUSERIAL_CFG *) &bt_reset_cfg);
+                                if (fd < 0) {
+                                    ALOGE("userial_vendor_open returns err");
                                     retval = -1;
-                                    break;
-                                }
+                                } else {
+                                    /* Clock on */
+                                    userial_clock_operation(fd, USERIAL_OP_CLK_ON);
+                                    ALOGD("userial clock on");
 
-                                /* Clock off */
-                                userial_clock_operation(fd, USERIAL_OP_CLK_ON);
+                                    /* Give some delay before clock and uart driver is ramping up and ready */
+                                    usleep(200); /* 200 us delay */
 
-                                /* Close uart port for the reset handler */
-                                userial_vendor_close();
+                                    /* UART TxD control as BT Reset*/
+                                    /* 0xFC = 3 bits = 8.6 us *3 =  25.8us */
+                                    len = write(fd, &reset_val, 1);
+                                    if (len != 1 ) {
+                                        ALOGE("%s: Send failed with ret value: %d", __FUNCTION__, len);
+                                        retval = -1;
+                                        break;
+                                    }
 
-                                /* For Cherokee, it need to wait for 100ms */
-                                usleep(100*1000);
+                                    /* Clock off */
+                                    userial_clock_operation(fd, USERIAL_OP_CLK_ON);
+
+                                    /* Close uart port for the reset handler */
+                                    userial_vendor_close();
+
+                                    /* For Cherokee, it need to wait for 100ms */
+                                    usleep(100*1000);
+			        }
                             }
                         }
                     case BT_SOC_ROME:
                         {
-                            wait_for_patch_download(is_ant_req);
+                            wait_for_patch_download(is_ant_req | is_fm_req);
                             property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
                             if (!is_soc_initialized()) {
                                 char* dlnd_inprog = is_ant_req ? "ant" : "bt";
@@ -916,6 +937,11 @@
                                          ALOGV("connect to ant channel");
                                          ant_fd = fd_filter = connect_to_local_socket("ant_sock");
                                      }
+                                     else if (is_fm_req && (btSocType >=BT_SOC_ROME && btSocType
+                                              < BT_SOC_RESERVED)) {
+                                              ALOGI("%s: connect to fm channel", __func__);
+                                              fm_fd = fd_filter = connect_to_local_socket("fm_sock");
+                                     }
                                      else
 #endif
                                      {
@@ -924,9 +950,9 @@
                                      }
 
                                      if (fd_filter != -1) {
-                                         ALOGV("%s: received the socket fd: %d is_ant_req: %d\n",
-                                                                     __func__, fd_filter, is_ant_req);
-                                         if((strcmp(emb_wp_mode, "true") == 0) && !is_ant_req) {
+                                         ALOGV("%s: received the socket fd: %d is_ant_req: %d is_fm_req :%d\n",
+                                             __func__, fd_filter, is_ant_req,is_fm_req);
+                                         if((strcmp(emb_wp_mode, "true") == 0) && !is_ant_req && !is_fm_req) {
                                              if (chipset_ver >= ROME_VER_3_0) {
                                                  /*  get rome supported feature request */
                                                  ALOGE("%s: %x08 %0x", __FUNCTION__,chipset_ver, ROME_VER_3_0);
@@ -935,7 +961,7 @@
                                          }
                                          if (!skip_init) {
                                              /*Skip if already sent*/
-                                             enable_controller_log(fd_filter, is_ant_req);
+                                             enable_controller_log(fd_filter, (is_ant_req || is_fm_req));
                                              skip_init = true;
                                          }
 
@@ -948,6 +974,8 @@
                                      else {
                                          if (is_ant_req)
                                              ALOGE("Unable to connect to ANT Server Socket!!!");
+                                         else if (is_fm_req)
+                                             ALOGE("Unable to connect to FM Server Socket!!!");
                                          else
                                              ALOGE("Unable to connect to BT Server Socket!!!");
                                          retval = -1;
@@ -981,6 +1009,17 @@
             }
             break;
 #endif
+        case BT_VND_OP_FM_USERIAL_CLOSE:
+            {
+                ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_CLOSE");
+                property_set("wc_transport.clean_up","1");
+                if (fm_fd != -1) {
+                    ALOGE("closing fm_fd");
+                    close(fm_fd);
+                    fm_fd = -1;
+                }
+            }
+            break;
 #endif
         case BT_VND_OP_USERIAL_CLOSE:
             {
@@ -1201,8 +1240,9 @@
         op(BT_VND_OP_ANT_USERIAL_CLOSE, NULL);
 #endif
 #endif
-        /*Close both BT channel*/
+        /*Close both BT and FM channel*/
         op(BT_VND_OP_USERIAL_CLOSE, NULL);
+        op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
         /*CTRL OFF twice to make sure hw
          * turns off*/
 #ifdef ENABLE_ANT
@@ -1231,18 +1271,22 @@
 /* Check for one of the cients ANT/BT patch download is already in
 ** progress if yes wait till complete
 */
-void wait_for_patch_download(bool is_ant_req) {
+void wait_for_patch_download(bool is_ant_fm_req) {
     ALOGV("%s:", __FUNCTION__);
     char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
     while (1) {
         property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
 
-        if(is_ant_req && !strcmp(inProgress,"bt") ) {
+        if(is_ant_fm_req && !(strcmp(inProgress,"bt")|| strcmp(inProgress,"fm")) ) {
            //ANT request, wait for BT to finish
            usleep(50000);
         }
-        else if(!is_ant_req && !strcmp(inProgress,"ant") ) {
-           //BT request, wait for ANT to finish
+        else if(!is_ant_fm_req && !(strcmp(inProgress,"ant")|| strcmp(inProgress,"fm")) ) {
+          //BT request, wait for ANT to finish
+           usleep(50000);
+        }
+        else if(is_ant_fm_req && !(strcmp(inProgress,"bt") || strcmp(inProgress,"ant")) ) {
+           //FM request, wait for ANT or BT to finish
            usleep(50000);
         }
         else {