Cleanup of hci layer

Remove unused variables and functions. Synchronized threads on fm
close and make the design modular.

Change-Id: I9bcba9f2b1740b73f52f199ae09c3f08f53499c9
diff --git a/fm_hci/Android.mk b/fm_hci/Android.mk
index 2546902..c164235 100644
--- a/fm_hci/Android.mk
+++ b/fm_hci/Android.mk
@@ -16,7 +16,7 @@
 LOCAL_CFLAGS += $(bdroid_CFLAGS)
 
 LOCAL_SRC_FILES := \
-	fm_hci.c
+    fm_hci.c
 
 LOCAL_SHARED_LIBRARIES := \
          libdl \
@@ -30,7 +30,8 @@
         $(BDROID_DIR)/hci/include \
         $(BDROID_DIR)/stack/include \
         $(BDROID_DIR)/osi/include \
-        $(LOCAL_PATH)/../helium
+        $(LOCAL_PATH)/../helium \
+        $(LOCAL_PATH)/fm_hci
 
 LOCAL_MODULE := libfm-hci
 LOCAL_MODULE_TAGS := optional
diff --git a/fm_hci/fm_hci.c b/fm_hci/fm_hci.c
index d559b74..4793295 100644
--- a/fm_hci/fm_hci.c
+++ b/fm_hci/fm_hci.c
@@ -39,7 +39,6 @@
 #include "wcnss_hci.h"
 #include <stdlib.h>
 #include <dlfcn.h>
-#include <sys/eventfd.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/socket.h>
@@ -50,260 +49,205 @@
 #include <sys/stat.h>
 #include <sys/un.h>
 #include <cutils/properties.h>
+#include <signal.h>
 
-int fm_fd;
 static int fm_hal_fd =0;
-fm_hal_cb *hal_cb;
 
 #define FM_VND_SERVICE_START "wc_transport.start_fmhci"
 #define WAIT_TIMEOUT 200000 /* 200*1000us */
 
-// The set of events one can send to the userial read thread.
-// Note that the values must be >= 0x8000000000000000 to guarantee delivery
-// of the message (see eventfd(2) for details on blocking behaviour).
-enum {
-    USERIAL_RX_EXIT     = 0x8000000000000000ULL
-};
-bt_vendor_interface_t *fm_vnd_if = NULL;
+static void fm_hci_exit(void *arg);
 
-void event_notification(uint16_t event)
+static void event_notification(struct fm_hci_t *hci, uint16_t event)
 {
-    pthread_mutex_lock(&fmHCIControlBlock.event_lock);
-    ready_events |= event;
-    pthread_cond_signal(&fmHCIControlBlock.event_cond);
+    pthread_mutex_lock(&hci->event_lock);
     ALOGI("%s: Notifying worker thread with event: %d", __func__, event);
-    pthread_mutex_unlock(&fmHCIControlBlock.event_lock);
+    ready_events |= event;
+    pthread_cond_broadcast(&hci->event_cond);
+    pthread_mutex_unlock(&hci->event_lock);
 }
-void init_vnd_if()
+
+static void rx_thread_exit_handler(int sig)
 {
-    void *dlhandle;
+    ALOGD("%s: sig = 0x%x", __func__, sig);
+    if (sig == SIGUSR1) {
+    ALOGE("Got the signal.. exiting");
+    pthread_exit(NULL);
+    }
+}
+
+static int vendor_init(struct fm_hci_t *hci)
+{
+    void *dlhandle = hci->dlhandle = NULL;
     unsigned char bdaddr[] = {0xaa, 0xbb, 0xcc, 0x11, 0x22, 0x33};
 
     dlhandle = dlopen("libbt-vendor.so", RTLD_NOW);
-    if (!dlhandle)
-    {
+    if (!dlhandle) {
         ALOGE("!!! Failed to load libbt-vendor.so !!!");
-        return;
+        goto err;
     }
 
-    fm_vnd_if = (bt_vendor_interface_t *) dlsym(dlhandle, "BLUETOOTH_VENDOR_LIB_INTERFACE");
-    if (!fm_vnd_if)
-    {
+    hci->vendor = (bt_vendor_interface_t *) dlsym(dlhandle, "BLUETOOTH_VENDOR_LIB_INTERFACE");
+    if (!hci->vendor) {
         ALOGE("!!! Failed to get bt vendor interface !!!");
-        return;
+        goto err;
     }
 
     ALOGI("FM-HCI: Registering the WCNSS HAL library by passing CBs and BD addr.");
-    fm_vnd_if->init(&fm_vendor_callbacks, bdaddr);
+    if (hci->vendor->init(&fm_vendor_callbacks, bdaddr) !=
+                FM_HC_STATUS_SUCCESS) {
+        ALOGE("FM vendor interface init failed");
+        goto err;
+    }
+
+    return FM_HC_STATUS_SUCCESS;
+
+err:
+    return FM_HC_STATUS_FAIL;
 }
 
-volatile uint16_t command_credits;
-
-/* De-queues the FM CMD from the TX_Q */
-void dequeue_fm_tx_cmd()
+static void vendor_close(struct fm_hci_t *hci)
 {
-    TX_Q *new_first, *new_last;
-    static int cmd_count = 0;
-    static uint8_t credits = 0;
-    uint8_t i;
-    uint8_t temp_1 = 0x11;
+    void *dlhandle = hci->dlhandle;
 
-    if (cmd_count >= MAX_FM_CMD_CNT) {
-        ALOGI("\n\n\t\tReached Max. CMD COUNT!!\n\n");
-        lib_running = 0;
-        return;
+    if (hci->vendor)
+        hci->vendor->cleanup();
+    if (dlhandle) {
+        dlclose(dlhandle);
+        dlhandle = NULL;
     }
-    /*
-     * Save the 'first' pointer and make it NULL.
-     * This is to allow the FM-HAL to enqueue more CMDs to the TX_Q
-     * without having to contend for the 'tx_q_lock' with the FM-HCI thread.
-     * Once the pointer to the 'first' element in the TX_Q is available,
-     * send all the commands in the queue to WCNSS FILTER based on the
-     * command credits provided by the Controller. If command credits are
-     * not available, then wait for the same.
-     */
-    pthread_mutex_lock(&fmHCIControlBlock.tx_q_lock);
-    if (!fmHCIControlBlock.first) {
-        ALOGI("No FM CMD available in the Q\n");
-        pthread_mutex_unlock(&fmHCIControlBlock.tx_q_lock);
-        return;
-    }
-    else {
-        new_first = fmHCIControlBlock.first;
-        new_last  = fmHCIControlBlock.last;
-        fmHCIControlBlock.first = fmHCIControlBlock.last = NULL;
-    }
-    pthread_mutex_unlock(&fmHCIControlBlock.tx_q_lock);
+    hci->vendor = NULL;
+}
 
-    //credits = command_credits;
+/* De-queues the FM CMD from the struct transmit_queue_t */
+static void dequeue_fm_tx_cmd(struct fm_hci_t *hci)
+{
+    struct transmit_queue_t *temp;
+    uint16_t count = 0, len = 0;
 
-    TX_Q *temp = new_first;
-    while(temp != NULL) {
+    ALOGD("%s", __func__);
+    while (1) {
+        pthread_mutex_lock(&hci->tx_q_lock);
+        temp = hci->first;
+        if (!temp) {
+            ALOGI("No FM CMD available in the Queue\n");
+            pthread_mutex_unlock(&hci->tx_q_lock);
+            return;
+        } else {
+            hci->first = temp->next;
+        }
+        pthread_mutex_unlock(&hci->tx_q_lock);
 
 wait_for_cmd_credits:
-        pthread_mutex_lock(&fmHCIControlBlock.credit_lock);
-        while (command_credits == 0) {
-              ALOGI("\n\n\t\tWaiting for COMMAND CREDITS from CONTROLLER\n\n");
-              pthread_cond_wait(&fmHCIControlBlock.cmd_credits_cond, &fmHCIControlBlock.credit_lock);
+        pthread_mutex_lock(&hci->credit_lock);
+        while (hci->command_credits == 0) {
+              pthread_cond_wait(&hci->cmd_credits_cond, &hci->credit_lock);
         }
-        pthread_mutex_unlock(&fmHCIControlBlock.credit_lock);
+        pthread_mutex_unlock(&hci->credit_lock);
 
         /* Check if we really got the command credits */
-        //REVISIT this area
-        //if (credits) {
-        if (command_credits) {
-            ALOGI("%s: Sending the FM-CMD(prot_byte: 0x%x): 0x%x dequeued from TX_Q\n", __func__, temp->hdr->protocol_byte, temp->hdr->opcode);
+        if (hci->command_credits) {
 
-            if (temp->hdr->plen) {
-                ALOGI("%s: CMD-PARAMS:", __func__);
-                for (i = 0; i < temp->hdr->plen; i++)
-                    ALOGI(" <0x%x> ", temp->hdr->cmd_params[i]);
-            } else
-                ALOGE("%s: NO CMD-PARAMS available for this command", __func__);
-
-            ALOGE("%s: Sizeof FM_HDR: %d", __func__, (int)sizeof(temp->hdr));
+            len = sizeof(struct fm_command_header_t) + temp->hdr->len;
+again:
             /* Use socket 'fd' to send the command down to WCNSS Filter */
-            write(fm_fd, (uint8_t *)temp->hdr, (sizeof(FM_HDR) + temp->hdr->plen));
-            //write(fd, &temp_1, 1);
+            count = write(hci->fd, (uint8_t *)temp->hdr + count, len);
+
+            if (count < len) {
+                len -= count;
+                goto again;
+            }
+            count = 0;
 
             /* Decrement cmd credits by '1' after sending the cmd*/
-            command_credits--;
-
-            /* TODO:
-             * Initialize 'cmd_cnt' to MAX_FM_CMD(?). Should we have any limit on the
-             * number of outstanding commands in the TX-Q ??
-             */
-            cmd_count--;
-
-            /* Fetch the next cmd to be sent */
-            temp = temp->next;
+            pthread_mutex_lock(&hci->credit_lock);
+            hci->command_credits--;
+            pthread_mutex_unlock(&hci->credit_lock);
         } else {
             if (!lib_running)
                 break;
-
-            ALOGI("\n\n\t\tFalse wakeup: Yet to get COMMAND CREDITS from CONTROLLER\n\n");
             goto wait_for_cmd_credits;
         }
     }
 }
 
-
-static int event_fd = -1;
-
-static inline int add_event_fd(fd_set *set) {
-    if (event_fd == -1) {
-      event_fd = eventfd(0, 0);
-      if (event_fd == -1) {
-          ALOGE("%s unable to create event fd: %s", __func__, strerror(errno));
-          return -1;
-      }
-    }
-
-    FD_SET(event_fd, set);
-    return event_fd;
-}
-
-static inline uint64_t read_event() {
-    assert(event_fd != -1);
-
-    uint64_t value = 0;
-    eventfd_read(event_fd, &value);
-    return value;
-}
-static inline void fm_send_event(uint64_t event_id) {
-    assert(event_fd != -1);
-    eventfd_write(event_fd, event_id);
-}
-
-static int read_fm_event(int fd, FM_EVT_HDR *pbuf, int len)
+static int read_fm_event(struct fm_hci_t *hci, struct fm_event_header_t *pbuf, int len)
 {
     fd_set readFds;
-    int n = 0, ret = -1, evt_type = -1, evt_len = -1;
+    sigset_t sigmask, emptymask;
+    int n = 0, ret = -1, evt_len = -1;
+    volatile int fd = hci->fd;
+    struct sigaction action;
+
+    sigemptyset(&sigmask);
+    sigaddset(&sigmask, SIGUSR1);
+    if (sigprocmask(SIG_BLOCK, &sigmask, NULL) == -1) {
+    ALOGE("failed to sigprocmask");
+    }
+    memset(&action, 0, sizeof(struct sigaction));
+    sigemptyset(&action.sa_mask);
+    action.sa_flags = 0;
+    action.sa_handler = rx_thread_exit_handler;
+
+    sigemptyset(&emptymask);
+
+    if (sigaction(SIGUSR1, &action, NULL) < 0) {
+    ALOGE("%s:sigaction failed", __func__);
+    }
 
     while (lib_running)
     {
         FD_ZERO(&readFds);
         FD_SET(fd, &readFds);
 
-        if (event_fd == -1) {
-            event_fd = eventfd(0, 0);
-            if (event_fd == -1) {
-                ALOGE("%s: unable to create event fd: %s", __func__, strerror(errno));
-                return -1;
-            }
-        }
-        FD_SET(event_fd, &readFds);
-        int fd_max = (event_fd > fd ? event_fd : fd);
-
         ALOGV("%s: Waiting for events from WCNSS FILTER...\n", __func__);
 
         /* Wait for event/data from WCNSS Filter */
-        n = select(fd_max+1, &readFds, NULL, NULL, NULL);
+        n = pselect(fd+1, &readFds, NULL, NULL, NULL, &emptymask);
         if (n > 0)
         {
             /* Check if event is available or not */
             if (FD_ISSET(fd, &readFds)) {
-                ret = read(fd, (uint8_t *)pbuf, (size_t)(sizeof(FM_EVT_HDR) + MAX_FM_EVT_PARAMS));
+                ret = read(fd, (uint8_t *)pbuf, (size_t)(sizeof(struct fm_event_header_t) + MAX_FM_EVT_PARAMS));
                 if (0 == ret) {
-                    ALOGD("%s: read() returned '0' bytes\n", __func__);
+                    ALOGV("%s: read() returned '0' bytes\n", __func__);
+                    break;
                 }
                 else {
                     ALOGV("%s: read() returned %d bytes of FM event/data\n", __func__, ret);
                     while (ret > 0) {
+                        pthread_mutex_lock(&hci->credit_lock);
                         if (pbuf->evt_code == FM_CMD_COMPLETE) {
-                            ALOGI("\n\t%s: Received %d bytes of CC event data from WCNSS FILTER!!!\n\t"
-                                "Evt type\t: 0x%x \n\tEvt Code\t: 0x%x \n\tEvt len\t\t: 0x%x \n\topcode\t\t: 0x%x%x \n\tCmd Credits\t: 0x%x \n\tStatus\t\t: 0x%x\n",
-                                __func__, ret, pbuf->protocol_byte, pbuf->evt_code, pbuf->evt_len, pbuf->cmd_params[2], pbuf->cmd_params[1],
-                            pbuf->cmd_params[0], pbuf->cmd_params[3]);
-                            evt_type = FM_CMD_COMPLETE;
+                            hci->command_credits = pbuf->params[0];
+                            pthread_cond_signal(&hci->cmd_credits_cond);
                         } else if (pbuf->evt_code == FM_CMD_STATUS) {
-                            ALOGI("\n\t%s: Received %d bytes of CS event data from WCNSS FILTER!!!\n\t"
-                                "Evt type\t: 0x%x \n\tEvt Code\t: 0x%x \n\tEvt len\t\t: 0x%x \n\topcode\t\t: 0x%x%x \n\tCmd Credits\t: 0x%x \n\tStatus\t\t: 0x%x\n",
-                                __func__, ret, pbuf->protocol_byte, pbuf->evt_code, pbuf->evt_len, pbuf->cmd_params[3], pbuf->cmd_params[2],
-                            pbuf->cmd_params[1], pbuf->cmd_params[0]);
-                            evt_type = FM_CMD_STATUS;
+                            hci->command_credits = pbuf->params[1];
+                            pthread_cond_signal(&hci->cmd_credits_cond);
                         } else if (pbuf->evt_code == FM_HW_ERR_EVENT) {
                               ALOGI("%s: FM H/w Err Event Recvd. Event Code: 0x%2x", __func__, pbuf->evt_code);
                               lib_running =0;
-                              fm_vnd_if->ssr_cleanup(0x22);
+                              hci->vendor->ssr_cleanup(0x22);
                         } else {
-                            ALOGI("%s: Not CS/CC Event: Recvd. Event Code: 0x%2x", __func__, pbuf->evt_code);
-                            evt_type = -1;
+                            ALOGE("%s: Not CS/CC Event: Recvd. Event Code: 0x%2x", __func__, pbuf->evt_code);
                         }
+                        pthread_mutex_unlock(&hci->credit_lock);
 
                         evt_len = pbuf->evt_len;
 
-                        /* Notify 'fmHCITask' about availability of event or data */
-                        ALOGI("%s: \nNotifying 'fmHCITask' availability of FM event or data...\n", __func__);
-                        event_notification(HC_EVENT_RX);
+                        /* Notify 'hci_tx_thread' about availability of event or data */
+                        ALOGI("%s: \nNotifying 'hci_tx_thread' availability of FM event or data...\n", __func__);
+                        event_notification(hci, HC_EVENT_RX);
 
-                        if (hal_cb && hal_cb->fm_evt_notify != NULL)
-                            hal_cb->fm_evt_notify((uint8_t *)pbuf);
+                        if (hci->cb && hci->cb->process_event)
+                            hci->cb->process_event(hci->private_data, (uint8_t *)pbuf);
                         else
                             ALOGE("%s: ASSERT $$$$$$ Callback function NULL $$$$$", __func__);
 
-                        if((evt_type == FM_CMD_STATUS) || (evt_type == FM_CMD_COMPLETE)) {
-                            /* Provide command credits to allow fmHCITask to send cmds */
-                            pthread_mutex_lock(&fmHCIControlBlock.credit_lock);
-                            if (evt_type == FM_CMD_COMPLETE) {
-                                ALOGD("\n%s: Command Credit(s): '%d' received as part of CC Event for FM-CMD: 0x%x%x \n", __func__, pbuf->cmd_params[0],
-                                     pbuf->cmd_params[2], pbuf->cmd_params[1]);
-                                command_credits = pbuf->cmd_params[0];
-                            } else if (evt_type == FM_CMD_STATUS) {
-                                ALOGI("\n%s: Command Credit(s): '%d' received as part of CS Event for FM-CMD: 0x%x%x \n", __func__, pbuf->cmd_params[1],
-                                    pbuf->cmd_params[3], pbuf->cmd_params[2]);
-                                command_credits = pbuf->cmd_params[1];
-                            }
-                            pthread_cond_signal(&fmHCIControlBlock.cmd_credits_cond);
-                            pthread_mutex_unlock(&fmHCIControlBlock.credit_lock);
-                        }
-
                         ret = ret - (evt_len + 3);
                         ALOGD("%s: Length of available bytes @ HCI Layer: %d", __func__, ret);
                         if (ret > 0) {
-                            ALOGD("%s: Remaining bytes of event/data: %d", __func__, ret);
-                            pbuf = (FM_EVT_HDR *)&pbuf->cmd_params[evt_len];
-                            ALOGD("%s: Protocol byte of next packet: 0x%2x", __func__, pbuf[0]);
+                            ALOGE("%s: Remaining bytes of event/data: %d", __func__, ret);
+                            pbuf = (struct fm_event_header_t *)&pbuf->params[evt_len];
                         }
                     }
                 } //end of processing the event
@@ -322,19 +266,19 @@
     return ret;
 }
 
-static void *userial_read_thread(void *arg)
+static void *hci_read_thread(void *arg)
 {
     int length;
+    struct fm_hci_t *hci = (struct fm_hci_t *)arg;
 
-    FM_EVT_HDR *evt_buf = (FM_EVT_HDR *) malloc(sizeof(FM_EVT_HDR) + MAX_FM_EVT_PARAMS);
+    struct fm_event_header_t *evt_buf = (struct fm_event_header_t *) malloc(sizeof(struct fm_event_header_t) + MAX_FM_EVT_PARAMS);
 
-    ALOGD("%s: Wait for events from the WCNSS Filter", __func__);
-    length = read_fm_event(fm_fd, evt_buf, sizeof(FM_EVT_HDR) + MAX_FM_EVT_PARAMS);
+    length = read_fm_event(hci, evt_buf, sizeof(struct fm_event_header_t) + MAX_FM_EVT_PARAMS);
     ALOGD("length=%d\n",length);
     if(length <=0) {
        lib_running =0;
     }
-    ALOGD("%s: Leaving userial_read_thread()", __func__);
+    ALOGV("%s: Leaving hci_read_thread()", __func__);
     pthread_exit(NULL);
     return arg;
 }
@@ -362,33 +306,39 @@
 }
 
 /*
- * Reads the FM-CMDs from the TX_Q and sends it down to WCNSS Filter
+ * Reads the FM-CMDs from the struct transmit_queue_t and sends it down to WCNSS Filter
  * Reads events sent by the WCNSS Filter and copies onto RX_Q
  */
-static void* fmHCITask(void *arg)
+static void* hci_tx_thread(void *arg)
 {
-    static uint16_t events;
-    uint16_t ret;
-    while (lib_running) {
-        pthread_mutex_lock(&fmHCIControlBlock.event_lock);
-        while (ready_events == 0) {
-            pthread_cond_wait(&fmHCIControlBlock.event_cond, &fmHCIControlBlock.event_lock);
-        }
-        events = ready_events;
-        ready_events = 0;
-        pthread_mutex_unlock(&fmHCIControlBlock.event_lock);
+    uint16_t events;
+    struct fm_hci_t *hci = (struct fm_hci_t *)arg;
 
-        if ((events & 0xFFF8) == HC_EVENT_TX) {
-        ALOGI("\n@@@@@ FM-HCI Task : EVENT_TX available @@@@@\n");
-        dequeue_fm_tx_cmd();
+    while (lib_running) {
+        pthread_mutex_lock(&hci->event_lock);
+        pthread_cond_wait(&hci->event_cond, &hci->event_lock);
+        ALOGE("%s: ready_events= %d", __func__, ready_events);
+        events = ready_events;
+        if (ready_events & HC_EVENT_TX)
+            ready_events &= (~HC_EVENT_TX);
+        if (ready_events & HC_EVENT_RX)
+            ready_events &= (~HC_EVENT_RX);
+        pthread_mutex_unlock(&hci->event_lock);
+
+        if (events & HC_EVENT_TX) {
+            dequeue_fm_tx_cmd(hci);
         }
-        if ((events & 0xFFF4) == HC_EVENT_RX) {
+        if (events & HC_EVENT_RX) {
              ALOGI("\n##### FM-HCI Task : EVENT_RX available #####\n");
         }
+        if (events & HC_EVENT_EXIT) {
+            ALOGE("GOT HC_EVENT_EXIT.. exiting");
+            break;
+        }
     }
 
-    ALOGE("%s: ##### Exiting fmHCITask Worker thread!!! #####", __func__);
-    return arg;
+    ALOGV("%s: ##### Exiting hci_tx_thread Worker thread!!! #####", __func__);
+    return NULL;
 }
 
 void stop_fmhal_service() {
@@ -435,122 +385,193 @@
         ALOGI("%s: Exit ", __func__);
 }
 
-int fm_hci_init(fm_hal_cb *p_cb)
+static int start_tx_thread(struct fm_hci_t *hci)
 {
-    pthread_attr_t thread_attr;
     struct sched_param param;
-    int policy, result, hci_type;
-
-    ALOGI("FM-HCI: init");
-    start_fmhal_service();
-    /* Save the FM-HAL event notofication callback func. */
-    hal_cb = p_cb;
-    fm_hal_fd =  connect_to_local_fmsocket("fmhal_sock");
-	if(fm_hal_fd != -1)
-    {
-       ALOGI("FM hal service socket connect success..");
-    }
-    ALOGI("fm_hal_fd = %d", fm_hal_fd);
-	//if(fm_hal_fd == -1)
-   //      return FM_HC_STATUS_FAIL;
-    ALOGI("%s: Initializing FM-HCI layer...", __func__);
-    lib_running = 1;
-    ready_events = 0;
-    command_credits = 1;
-
-    pthread_mutex_init(&fmHCIControlBlock.tx_q_lock, NULL);
-    pthread_mutex_init(&fmHCIControlBlock.credit_lock, NULL);
-    pthread_mutex_init(&fmHCIControlBlock.event_lock, NULL);
-
-    pthread_cond_init(&fmHCIControlBlock.event_cond, NULL);
-    pthread_cond_init(&fmHCIControlBlock.cmd_credits_cond, NULL);
-
-    pthread_attr_init(&thread_attr);
+    int policy, result;
 
     ALOGI("FM-HCI: Creating the FM-HCI TASK...");
-    if (pthread_create(&fmHCIControlBlock.fmHCITaskThreadId, &thread_attr, \
-                       fmHCITask, NULL) != 0)
+    if (pthread_create(&hci->tx_thread, NULL, hci_tx_thread, hci) != 0)
     {
         ALOGE("pthread_create failed!");
         lib_running = 0;
         return FM_HC_STATUS_FAIL;
     }
 
-    ALOGI("FM-HCI: Configuring the scheduling policy and priority of the FM HCI thread");
-    if(pthread_getschedparam(fmHCIControlBlock.fmHCITaskThreadId, &policy, &param)==0)
+    if(pthread_getschedparam(hci->tx_thread, &policy, &param)==0)
     {
         policy = SCHED_NORMAL;
 #if (BTHC_LINUX_BASE_POLICY!=SCHED_NORMAL)
         param.sched_priority = BTHC_MAIN_THREAD_PRIORITY;
 #endif
-        result = pthread_setschedparam(fmHCIControlBlock.fmHCITaskThreadId, policy, &param);
+        result = pthread_setschedparam(hci->tx_thread, policy, &param);
         if (result != 0)
         {
-            ALOGW("libbt-hci init: pthread_setschedparam failed (%s)", \
-                  strerror(result));
+            ALOGW("libbt-hci init: pthread_setschedparam failed (%d)", \
+                  result);
         }
     } else
         ALOGI("FM-HCI: Failed to get the Scheduling parameters!!!");
 
-	ALOGI("FM-HCI: Loading the WCNSS HAL library...");
-    init_vnd_if();
     return FM_HC_STATUS_SUCCESS;
 }
 
-
-int fm_power(fm_power_state state)
+static void stop_tx_thread(struct fm_hci_t *hci)
 {
-    int i,opcode,ret;
- 	int init_success = 0;
-    char value[PROPERTY_VALUE_MAX] = {'\0'};
-    if (fm_hal_fd)
-    {
-        if (state)
-            opcode = 2;
-        else {
-            opcode = 1;
+    int ret;
+
+    ALOGV("%s++", __func__);
+    if ((ret = pthread_kill(hci->tx_thread, SIGUSR1))
+            == FM_HC_STATUS_SUCCESS) {
+        ALOGE("%s:pthread_join", __func__);
+         if ((ret = pthread_join(hci->tx_thread, NULL)) != FM_HC_STATUS_SUCCESS)
+             ALOGE("Error joining tx thread, error = %d (%s)",
+                     ret, strerror(ret));
+    } else {
+        ALOGE("Error killing tx thread, error = %d (%s)",
+                ret, strerror(ret));
+    }
+}
+
+static void *hci_mon_thread(void *arg)
+{
+    struct fm_hci_t *hci = (struct fm_hci_t *)arg;
+    uint16_t events;
+    ALOGV("%s", __func__);
+
+    while (lib_running) {
+        pthread_mutex_lock(&hci->event_lock);
+        if (!(ready_events & HC_EVENT_EXIT))
+            pthread_cond_wait(&hci->event_cond, &hci->event_lock);
+        events = ready_events;
+        if (ready_events & HC_EVENT_EXIT)
+            ready_events &= (~HC_EVENT_EXIT);
+        pthread_mutex_unlock(&hci->event_lock);
+
+        ALOGD("events = 0x%x", events);
+        if (events & HC_EVENT_EXIT) {
+            ALOGD("Got Exit event.. Exiting HCI");
+            fm_hci_exit(hci);
+            break;
         }
-        ALOGI("%s:opcode: %x", LOG_TAG, opcode);
-        ret = write(fm_hal_fd,&opcode, 1);
-	    if (ret < 0)
-	 	{
-            ALOGE("failed to write fm hal socket");
-	 	}
     }
-    else {
-  	    ALOGE("Connect to socket failed ..");
-           ret = -1;
+    ALOGV("%s--", __func__);
+    return NULL;
+}
+
+static int start_mon_thread(struct fm_hci_t *hci)
+{
+    int ret = FM_HC_STATUS_SUCCESS;
+    ALOGD("%s", __func__);
+    if ((ret = pthread_create(&hci->mon_thread, NULL,
+                    hci_mon_thread, hci)) !=0) {
+        ALOGE("pthread_create failed! status = %d (%s)",
+                ret, strerror(ret));
+        lib_running = 0;
     }
-    if(state == FM_RADIO_DISABLE) {
-		for (i=0; i<10; i++) {
-	       property_get("wc_transport.fm_power_status", value, "0");
-		   if (strcmp(value, "0") == 0) {
-			   init_success = 1;
-			   break;
-           } else {
-                usleep(WAIT_TIMEOUT);
-           }
-       }
-        ALOGI("fm power OFF status:%d after %f seconds \n", init_success, 0.2*i);
-	 	stop_fmhal_service();
+    return ret;
+}
+
+static void stop_mon_thread(struct fm_hci_t *hci)
+{
+    int ret;
+    ALOGV("%s++", __func__);
+    if ((ret = pthread_kill(hci->mon_thread, SIGUSR1))
+            == FM_HC_STATUS_SUCCESS) {
+        ALOGE("%s:pthread_join", __func__);
+        if ((ret = pthread_join(hci->mon_thread, NULL)) != FM_HC_STATUS_SUCCESS)
+            ALOGE("Error joining mon thread, error = %d (%s)",
+                    ret, strerror(ret));
+    } else {
+        ALOGE("Error killing mon thread, error = %d (%s)",
+                ret, strerror(ret));
     }
-    if (state == FM_RADIO_ENABLE) {
-	   for (i=0; i<10; i++) {
-	       property_get("wc_transport.fm_power_status", value, "0");
-		   if (strcmp(value, "1") == 0) {
-			   init_success = 1;
-			   break;
-           } else {
-                usleep(WAIT_TIMEOUT);
-           }
-       }
-       ALOGI("fm power ON status:%d after %f seconds \n", init_success, 0.2*i);
+}
+
+static int start_rx_thread(struct fm_hci_t *hci)
+{
+    int ret = FM_HC_STATUS_SUCCESS;
+    ALOGV("%s++", __func__);
+
+    ALOGD("%s: Starting the userial read thread....", __func__);
+    if ((ret = pthread_create(&hci->rx_thread, NULL, \
+                       hci_read_thread, hci)) != 0) {
+        ALOGE("pthread_create failed! status = %d (%s)",
+                ret, strerror(ret));
+        lib_running = 0;
     }
-     return ret;
+    return ret;
+}
+
+static void stop_rx_thread(struct fm_hci_t *hci)
+{
+    int ret;
+    ALOGV("%s++", __func__);
+    if ((ret = pthread_kill(hci->rx_thread, SIGUSR1))
+            == FM_HC_STATUS_SUCCESS) {
+        ALOGE("%s:pthread_join", __func__);
+        if ((ret = pthread_join(hci->rx_thread, NULL)) != FM_HC_STATUS_SUCCESS)
+            ALOGE("Error joining rx thread, error = %d (%s)",
+                    ret, strerror(ret));
+    } else {
+        ALOGE("Error killing rx thread, error = %d (%s)",
+                ret, strerror(ret));
+    }
+}
+
+static int power(struct fm_hci_t *hci, fm_power_state_t state)
+{
+        int i,opcode,ret;
+        int init_success = 0;
+        char value[PROPERTY_VALUE_MAX] = {'\0'};
+        if (fm_hal_fd)
+        {
+            if (state)
+                opcode = 2;
+            else {
+                opcode = 1;
+            }
+            ALOGI("%s:opcode: %x", LOG_TAG, opcode);
+            ret = write(fm_hal_fd,&opcode, 1);
+            if (ret < 0) {
+                ALOGE("failed to write fm hal socket");
+            } else {
+                ret = FM_HC_STATUS_SUCCESS;
+            }
+        } else {
+            ALOGE("Connect to socket failed ..");
+            ret = -1;
+        }
+        if (state == FM_RADIO_DISABLE) {
+            for (i=0; i<10; i++) {
+                property_get("wc_transport.fm_power_status", value, "0");
+                if (strcmp(value, "0") == 0) {
+                    init_success = 1;
+                    break;
+                } else {
+                    usleep(WAIT_TIMEOUT);
+                }
+            }
+            ALOGI("fm power OFF status:%d after %f seconds \n", init_success, 0.2*i);
+            stop_fmhal_service();
+        }
+        if (state == FM_RADIO_ENABLE) {
+            for (i=0; i<10; i++) {
+                property_get("wc_transport.fm_power_status", value, "0");
+                if (strcmp(value, "1") == 0) {
+                    init_success = 1;
+                    break;
+                } else {
+                    usleep(WAIT_TIMEOUT);
+                }
+            }
+            ALOGI("fm power ON status:%d after %f seconds \n", init_success, 0.2*i);
+        }
+        return ret;
 }
 
 #define CH_MAX 3
-int open_serial_port()
+static int serial_port_init(struct fm_hci_t *hci)
 {
     int i, ret;
     int fd_array[CH_MAX];
@@ -559,110 +580,198 @@
         fd_array[i] = -1;
 
     ALOGI("%s: Opening the TTy Serial port...", __func__);
-    ret = fm_vnd_if->op(BT_VND_OP_FM_USERIAL_OPEN, &fd_array);
+    ret = hci->vendor->op(BT_VND_OP_FM_USERIAL_OPEN, &fd_array);
 
-    fm_fd = fd_array[0];
-    if (fm_fd == -1) {
+    if (fd_array[0] == -1) {
         ALOGE("%s unable to open TTY serial port", __func__);
         goto err;
     }
+    hci->fd = fd_array[0];
 
-    //TODO: Start the userial read thread here
-    ALOGE("%s: Starting the userial read thread....", __func__);
-    if (pthread_create(&fmHCIControlBlock.fmRxTaskThreadId, NULL, \
-                       userial_read_thread, NULL) != 0)
-    {
-        ALOGE("pthread_create failed!");
-        lib_running = 0;
-        return FM_HC_STATUS_FAIL;
-    }
-    return 0;
+    return FM_HC_STATUS_SUCCESS;
+
 err:
-    ALOGI("%s: Closing the TTy Serial port due to error!!!", __func__);
-    ret = fm_vnd_if->op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
-    return -1;
+    return FM_HC_STATUS_FAIL;
 }
 
-int enqueue_fm_tx_cmd(FM_HDR *pbuf)
+static void serial_port_close(struct fm_hci_t *hci)
 {
+    //TODO: what if hci/fm_vnd_if is null.. need to take lock and check
+    ALOGI("%s: Closing the TTy Serial port!!!", __func__);
+    hci->vendor->op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
+    hci->fd = -1;
+}
 
-    pthread_mutex_lock(&fmHCIControlBlock.tx_q_lock);
+static int enqueue_fm_tx_cmd(struct fm_hci_t *hci, struct fm_command_header_t *pbuf)
+{
+    struct transmit_queue_t *element =  (struct transmit_queue_t *) malloc(sizeof(struct transmit_queue_t));
 
-    if (!fmHCIControlBlock.first) {
-        fmHCIControlBlock.first = (TX_Q *) malloc(sizeof(TX_Q));
-        if (!fmHCIControlBlock.first) {
-            ALOGI("Failed to allocate memory for first!!\n");
-            pthread_mutex_unlock(&fmHCIControlBlock.tx_q_lock);
-            return FM_HC_STATUS_NOMEM;
-        }
-        fmHCIControlBlock.first->hdr = pbuf;
-        fmHCIControlBlock.first->next = NULL;
-        fmHCIControlBlock.last = fmHCIControlBlock.first;
-        ALOGI("%s: FM-CMD ENQUEUED SUCCESSFULLY", __func__);
-    } else {
-        TX_Q *element =  (TX_Q *) malloc(sizeof(TX_Q));
-        if (!element) {
-            ALOGI("Failed to allocate memory for element!!\n");
-            pthread_mutex_unlock(&fmHCIControlBlock.tx_q_lock);
-            return FM_HC_STATUS_NOMEM;
-        }
-        fmHCIControlBlock.last->next = element;
-        element->hdr = pbuf;
-        element->next = NULL;
-        fmHCIControlBlock.last = element;
-        ALOGI("%s: fm-cmd enqueued successfully", __func__);
+    if (!element) {
+        ALOGI("Failed to allocate memory for element!!\n");
+        return FM_HC_STATUS_NOMEM;
     }
+    element->hdr = pbuf;
+    element->next = NULL;
 
-    pthread_mutex_unlock(&fmHCIControlBlock.tx_q_lock);
+    pthread_mutex_lock(&hci->tx_q_lock);
+
+    if (!hci->first) {
+        hci->last = hci->first = element;
+    } else {
+        hci->last->next = element;
+        hci->last = element;
+    }
+    ALOGI("%s: FM-CMD ENQUEUED SUCCESSFULLY", __func__);
+
+    pthread_mutex_unlock(&hci->tx_q_lock);
+
     return FM_HC_STATUS_SUCCESS;
 }
 
-/** Transmit frame */
-int transmit(FM_HDR *pbuf)
+int fm_hci_transmit(void *hci, struct fm_command_header_t *buf)
 {
     int status = FM_HC_STATUS_FAIL;
 
-    if ((status = enqueue_fm_tx_cmd(pbuf)) == FM_HC_STATUS_SUCCESS)
-        event_notification(HC_EVENT_TX);
-    /* Cleanup Threads if Disable command sent */
-    if ((pbuf->opcode == hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
-                    HCI_OCF_FM_DISABLE_RECV_REQ))) {
-        ALOGD("FM Disable cmd. Waiting for threads to finish");
-        if ((status = pthread_join(fmHCIControlBlock.fmHCITaskThreadId, NULL)))
-            ALOGE("Failed to join HCI task thread. err = %d", status);
-        if ((status = pthread_join(fmHCIControlBlock.fmRxTaskThreadId, NULL)))
-            ALOGE("Failed to join HCI reader thread. err = %d", status);
-        pthread_cond_destroy(&fmHCIControlBlock.cmd_credits_cond);
-        pthread_cond_destroy(&fmHCIControlBlock.event_cond);
-        pthread_mutex_destroy(&fmHCIControlBlock.event_lock);
-        pthread_mutex_destroy(&fmHCIControlBlock.credit_lock);
-        pthread_mutex_destroy(&fmHCIControlBlock.tx_q_lock);
-        ALOGD("All Threads are done. Exiting.");
+    if (!hci || !buf) {
+        ALOGE("NULL input arguments");
+        return FM_HC_STATUS_NULL_POINTER;
     }
 
+    if ((status = enqueue_fm_tx_cmd((struct fm_hci_t *)hci, buf))
+            == FM_HC_STATUS_SUCCESS)
+        event_notification(hci, HC_EVENT_TX);
+
     return status;
 }
 
-void userial_close_reader(void) {
-    // Join the reader thread if it is still running.
-    if (lib_running) {
-        fm_send_event(USERIAL_RX_EXIT);
-        int result = pthread_join(fmHCIControlBlock.fmRxTaskThreadId, NULL);
-        if (result)
-            ALOGE("%s failed to join reader thread: %d", __func__, result);
+void fm_hci_close(void *arg) {
+
+    ALOGV("%s  close fm userial ", __func__);
+
+    struct fm_hci_t *hci = (struct fm_hci_t *)arg;
+    if (!hci) {
+        ALOGE("NULL arguments");
         return;
     }
-    ALOGW("%s Already closed userial reader thread", __func__);
+    event_notification(hci, HC_EVENT_EXIT);
 }
 
-void fm_userial_close(void) {
+int fm_hci_init(fm_hci_hal_t *hci_hal)
+{
+    int ret = FM_HC_STATUS_FAIL;
+    struct fm_hci_t *hci = NULL;
+    ALOGV("++%s", __func__);
 
-    ALOGD("%s  close fm userial ", __func__);
+    if (!hci_hal || !hci_hal->hal) {
+        ALOGE("NULL input argument");
+        return FM_HC_STATUS_NULL_POINTER;
+    }
+
+    hci = malloc(sizeof(struct fm_hci_t));
+    if (!hci) {
+        ALOGE("Failed to malloc hci context");
+        return FM_HC_STATUS_NOMEM;
+    }
+    memset(hci, 0, sizeof(struct fm_hci_t));
+
+    lib_running = 1;
+    ready_events = 0;
+    hci->command_credits = 1;
+    hci->fd = -1;
+
+    pthread_mutex_init(&hci->tx_q_lock, NULL);
+    pthread_mutex_init(&hci->credit_lock, NULL);
+    pthread_mutex_init(&hci->event_lock, NULL);
+
+    pthread_cond_init(&hci->event_cond, NULL);
+    pthread_cond_init(&hci->cmd_credits_cond, NULL);
+
+    start_fmhal_service();
+    fm_hal_fd = connect_to_local_fmsocket("fmhal_sock");
+    if (fm_hal_fd == -1) {
+        ALOGI("FM hal service socket connect failed..");
+        goto err_socket;
+    }
+    ALOGI("fm_hal_fd = %d", fm_hal_fd);
+
+    ret = vendor_init(hci);
+    if (ret)
+        goto err_vendor;
+    ret = power(hci, FM_RADIO_ENABLE);
+    if (ret)
+        goto err_power;
+    ret = serial_port_init(hci);
+    if (ret)
+        goto err_serial;
+    ret = start_mon_thread(hci);
+    if (ret)
+        goto err_thread_mon;
+    ret = start_tx_thread(hci);
+    if (ret)
+        goto err_thread_tx;
+    ret = start_rx_thread(hci);
+    if (ret)
+        goto err_thread_rx;
+
+    hci->cb = hci_hal->cb;
+    hci->private_data = hci_hal->hal;
+    hci_hal->hci = hci;
+    ALOGD("--%s success", __func__);
+    return FM_HC_STATUS_SUCCESS;
+
+err_thread_rx:
+    stop_rx_thread(hci);
+err_thread_tx:
+    stop_tx_thread(hci);
+err_thread_mon:
+    stop_mon_thread(hci);
+err_serial:
+    serial_port_close(hci);
+err_power:
+    power(hci, FM_RADIO_DISABLE);
+err_vendor:
+    vendor_close(hci);
+err_socket:
+    stop_fmhal_service();
+
+    pthread_mutex_destroy(&hci->tx_q_lock);
+    pthread_mutex_destroy(&hci->credit_lock);
+    pthread_mutex_destroy(&hci->event_lock);
+    pthread_cond_destroy(&hci->event_cond);
+    pthread_cond_destroy(&hci->cmd_credits_cond);
+
     lib_running = 0;
-    fm_vnd_if->op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
-    fm_fd = -1;
-    ready_events = HC_EVENT_EXIT;
-    pthread_cond_signal(&fmHCIControlBlock.event_cond);
-    pthread_cond_signal(&fmHCIControlBlock.cmd_credits_cond);
-    // Free all buffers still waiting in the RX queue.
+    ready_events = 0;
+    hci->command_credits = 0;
+    free(hci);
+
+    ALOGE("--%s fail", __func__);
+    return ret;
 }
+
+static void fm_hci_exit(void *arg)
+{
+    struct fm_hci_t *hci = (struct fm_hci_t *)arg;
+    ALOGE("%s", __func__);
+
+    lib_running = 0;
+    ready_events = HC_EVENT_EXIT;
+    hci->command_credits = 0;
+    serial_port_close(hci);
+    power(hci, FM_RADIO_DISABLE);//need to address this
+    vendor_close(hci);
+    pthread_cond_broadcast(&hci->event_cond);
+    pthread_cond_broadcast(&hci->cmd_credits_cond);
+    stop_rx_thread(hci);
+    stop_tx_thread(hci);
+    ALOGD("Tx, Rx Threads join done");
+    pthread_mutex_destroy(&hci->tx_q_lock);
+    pthread_mutex_destroy(&hci->credit_lock);
+    pthread_mutex_destroy(&hci->event_lock);
+    pthread_cond_destroy(&hci->event_cond);
+    pthread_cond_destroy(&hci->cmd_credits_cond);
+
+    free(hci);
+    hci = NULL;
+}
+
diff --git a/fm_hci/fm_hci.h b/fm_hci/fm_hci.h
index cfacb84..8818068 100644
--- a/fm_hci/fm_hci.h
+++ b/fm_hci/fm_hci.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -30,24 +30,9 @@
 #ifndef __FM_HCI__
 #define __FM_HCI__
 
-#pragma pack(1)
-
-#include <radio-helium.h>
-
-/** Host/Controller Library Return Status */
-typedef enum {
-    FM_HC_STATUS_SUCCESS,
-    FM_HC_STATUS_FAIL,
-    FM_HC_STATUS_NOT_READY,
-    FM_HC_STATUS_NOMEM,
-    FM_HC_STATUS_BUSY,
-    FM_HC_STATUS_CORRUPTED_BUFFER
-} fm_hc_status_t;
-
-typedef enum {
-    FM_RADIO_DISABLE,
-    FM_RADIO_ENABLE
-}fm_power_state;
+#include "bt_hci_bdroid.h"
+#include "bt_vendor_lib.h"
+#include "fm_hci_api.h"
 
 /* Host/Controller lib internal event ID */
 #define HC_EVENT_PRELOAD               0x0001
@@ -71,56 +56,46 @@
 #define FM_CMD_STATUS   0x10
 #define FM_HW_ERR_EVENT 0x1A
 
-static pthread_mutex_t utils_mutex;
-
+/* TODO: move inside context */
 static volatile uint8_t lib_running = 0;
 static volatile uint16_t ready_events = 0;
 
-FILE *fd_wcnss_filter;
+// The set of events one can send to the userial read thread.
+// Note that the values must be >= 0x8000000000000000 to guarantee delivery
+// of the message (see eventfd(2) for details on blocking behaviour).
+enum {
+    USERIAL_RX_EXIT     = 0x8000000000000000ULL
+};
 
-typedef struct {
-    uint8_t protocol_byte;
-    uint16_t opcode;
-    uint8_t plen;
-    uint8_t cmd_params[];
-} FM_HDR;
+struct transmit_queue_t {
+    struct fm_command_header_t *hdr;
+    struct transmit_queue_t *next;
+};
 
-typedef struct {
-    uint8_t protocol_byte;
-    uint8_t evt_code;
-    uint8_t evt_len;
-    uint8_t cmd_params[];
-} FM_EVT_HDR;
-
-typedef struct hdr
-{
-    FM_HDR  *hdr;
-    struct hdr *next;
-} TX_Q;
-
-int transmit(FM_HDR *pbuf);
-int  fm_hci_init(fm_hal_cb *);
-int fm_power(fm_power_state state);
-int open_serial_port(void);
-void fm_userial_close(void);
-
-typedef struct {
-    pthread_mutex_t tx_q_lock;
+struct fm_hci_t {
+    int fd;
     pthread_mutex_t credit_lock;
-    pthread_mutex_t event_lock;
-
-    pthread_cond_t event_cond;
     pthread_cond_t cmd_credits_cond;
 
-    pthread_t fmHALTaskThreadId;
-    pthread_t fmHCITaskThreadId;
-    pthread_t fmRxTaskThreadId;
+    pthread_mutex_t event_lock;
+    pthread_cond_t event_cond;
 
-    TX_Q *first;
-    TX_Q *last;
+    pthread_t hal_thread;
+    pthread_t tx_thread;
+    pthread_t rx_thread;
+    pthread_t mon_thread;
 
-} fmHCIControlStructure;
+    pthread_mutex_t tx_q_lock;
+    struct transmit_queue_t *first;
+    struct transmit_queue_t *last;
 
-fmHCIControlStructure fmHCIControlBlock;
+    void *dlhandle;
+    bt_vendor_interface_t *vendor;
+
+    struct fm_hci_callbacks_t *cb;
+    void *private_data;
+    volatile uint16_t command_credits;
+};
 
 #endif
+
diff --git a/fm_hci/fm_hci_api.h b/fm_hci/fm_hci_api.h
new file mode 100644
index 0000000..67a866b
--- /dev/null
+++ b/fm_hci/fm_hci_api.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *        * Redistributions of source code must retain the above copyright
+ *            notice, this list of conditions and the following disclaimer.
+ *        * Redistributions in binary form must reproduce the above
+ *            copyright notice, this list of conditions and the following
+ *            disclaimer in the documentation and/or other materials provided
+ *            with the distribution.
+ *        * Neither the name of The Linux Foundation nor the names of its
+ *            contributors may be used to endorse or promote products derived
+ *            from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FM_HCI_API__
+#define __FM_HCI_API__
+
+
+/** Host/Controller Library Return Status */
+typedef enum {
+    FM_HC_STATUS_SUCCESS,
+    FM_HC_STATUS_FAIL,
+    FM_HC_STATUS_NOT_READY,
+    FM_HC_STATUS_NOMEM,
+    FM_HC_STATUS_BUSY,
+    FM_HC_STATUS_CORRUPTED_BUFFER,
+    FM_HC_STATUS_NULL_POINTER,
+} fm_hc_status_t;
+
+static char *status_s[] = {
+    "Success",
+    "Failed, generic error",
+    "Not ready",
+    "Memory not available",
+    "Resource busy",
+    "Buffer is corrupted",
+    "NULL pointer dereference",
+};
+
+static inline char *fm_hci_status(int status) {
+    return status_s[status];
+}
+
+typedef enum {
+    FM_RADIO_DISABLE,
+    FM_RADIO_ENABLE
+} fm_power_state_t;
+
+typedef int (*event_notification_cb_t)(void *hal, unsigned char *buf);
+
+struct fm_hci_callbacks_t {
+    event_notification_cb_t process_event;
+};
+
+typedef struct {
+    void *hci;
+    void *hal;
+    struct fm_hci_callbacks_t *cb;
+}fm_hci_hal_t;
+
+struct fm_command_header_t {
+    uint8_t  pi;                /* packet indicator */
+    uint16_t opcode;
+    uint8_t  len;
+    uint8_t  params[];
+}__attribute__((packed));
+
+struct fm_event_header_t {
+    uint8_t pi;                /* packet indicator */
+    uint8_t evt_code;
+    uint8_t evt_len;
+    uint8_t params[];
+}__attribute__((packed));
+
+int fm_hci_init(fm_hci_hal_t *hal_hci);
+int fm_hci_transmit(void *hci, struct fm_command_header_t *buf);
+void fm_hci_close(void *hci);
+#endif
diff --git a/helium/radio-helium.h b/helium/radio-helium.h
index 30c3d0c..a67c981 100644
--- a/helium/radio-helium.h
+++ b/helium/radio-helium.h
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2015, The Linux Foundation. All rights reserved.
+Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -27,14 +27,11 @@
 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#ifndef __UAPI_RADIO_HCI_CORE_H
-#define __UAPI_RADIO_HCI_CORE_H
-
-#pragma pack(1)
+#ifndef __RADIO_HELIUM_H__
+#define __RADIO_HELIUM_H__
 
 #include <stdbool.h>
 
-pthread_mutex_t fm_hal;
 #define MIN_TX_TONE_VAL  0x00
 #define MAX_TX_TONE_VAL  0x07
 #define MIN_HARD_MUTE_VAL  0x00
@@ -82,11 +79,6 @@
 #define MIN_BLEND_HI  -128
 #define MAX_BLEND_HI  127
 
-
-/* ---- HCI Packet structures ---- */
-#define RADIO_HCI_COMMAND_HDR_SIZE sizeof(struct radio_hci_command_hdr)
-#define RADIO_HCI_EVENT_HDR_SIZE   sizeof(struct radio_hci_event_hdr)
-
 /* HCI data types */
 #define RADIO_HCI_COMMAND_PKT   0x11
 #define RADIO_HCI_EVENT_PKT     0x14
@@ -198,12 +190,12 @@
     ert_cb  ert_update_cb;
     disable_cb  disabled_cb;
     rds_grp_cntrs_cb rds_grp_cntrs_rsp_cb;
-	rds_grp_cntrs_ext_cb rds_grp_cntrs_ext_rsp_cb;
+    rds_grp_cntrs_ext_cb rds_grp_cntrs_ext_rsp_cb;
     fm_peek_cb fm_peek_rsp_cb;
     fm_ssbi_peek_cb fm_ssbi_peek_rsp_cb;
     fm_agc_gain_cb fm_agc_gain_rsp_cb;
     fm_ch_det_th_cb fm_ch_det_th_rsp_cb;
-    fm_ecc_evt_cb	ext_country_code_cb;
+    fm_ecc_evt_cb  ext_country_code_cb;
     callback_thread_event thread_evt_cb;
     fm_sig_thr_cb fm_get_sig_thres_cb;
     fm_get_ch_det_thrs_cb fm_get_ch_det_thr_cb;
@@ -214,46 +206,7 @@
     fm_set_blnd_cb fm_set_blend_cb;
     fm_get_stn_prm_cb fm_get_station_param_cb;
     fm_get_stn_dbg_prm_cb fm_get_station_debug_param_cb;
-} fm_vendor_callbacks_t;
-
-pthread_mutex_t radio_fm_cmd;
-typedef struct {
-    int (*init)(const fm_vendor_callbacks_t *p_cb);
-    int (*set_fm_ctrl)(int opcode, int val);
-    void (*Get_fm_ctrl) (int opcode, int val);
-} fm_interface_t;
-
-typedef int (*fm_evt_notify_cb)(unsigned char *p_buf);
-
-typedef struct {
-    fm_evt_notify_cb fm_evt_notify;
-} fm_hal_cb;
-
-struct radio_hci_command_hdr {
-    short  opcode; /* OCF & OGF */
-    char   plen;
-} ;
-
-struct radio_hci_event_hdr {
-    char  evt;
-    char  plen;
-} ;
-
-struct radio_hci_dev {
-    char  name[8];
-    unsigned long  flags;
-    short  id;
-    char  bus;
-    char  dev_type;
-    char  dev_name[248];
-    char  dev_class[3];
-    char  features[8];
-    char  commands[64];
-    unsigned int  data_block_len;
-    unsigned long  cmd_last_tx;
-    int  req_status;
-    int  req_result;
-};
+} fm_hal_callbacks_t;
 
 /* Opcode OCF */
 /* HCI recv control commands opcode */
@@ -384,7 +337,6 @@
     int   band_high_limit;
 } ;
 
-
 /* ----- HCI Command request ----- */
 struct hci_fm_tx_ps {
     char   ps_control;
@@ -612,7 +564,7 @@
     char    mute_mode;
     char    sinr;
     char    intf_det_th;
-} ;
+}__attribute__((packed)) ;
 
 struct rds_blk_data {
     char  rdsMsb;
@@ -653,25 +605,25 @@
     short   pi_code;
     char    af_size;
     char    af_list[FM_AF_LIST_MAX_SIZE];
-} ;
+} __attribute__((packed)) ;
 
 struct hci_ev_cmd_complete {
     char    num_hci_cmd_pkts;
     short   cmd_opcode;
-} ;
+} __attribute((packed));
 
 struct hci_ev_cmd_status {
     char    status;
     char    num_hci_cmd_pkts;
     short   status_opcode;
-} ;
+} __attribute__((packed));
 
 struct hci_ev_srch_st {
     int    station_freq;
     char    rds_cap;
     char   pty;
     short   status_opcode;
-} ;
+} __attribute__((packed));
 
 struct hci_ev_rel_freq {
     char  rel_freq_msb;
@@ -687,18 +639,19 @@
 struct hci_fm_conf_rsp {
     char    status;
     struct hci_fm_recv_conf_req recv_conf_rsp;
-} ;
+} __attribute__((packed));
 
 struct hci_fm_rds_grp_cntrs_rsp {
     char    status;
     struct hci_fm_rds_grp_cntrs_params recv_rds_grp_cntrs_rsp;
-} ;
+} __attribute__((packed));
 
 
 struct hci_fm_get_trans_conf_rsp {
     char    status;
     struct hci_fm_trans_conf_req_struct trans_conf_rsp;
-} ;
+} __attribute__((packed));
+
 struct hci_fm_sig_threshold_rsp {
     char    status;
     char    sig_threshold;
@@ -711,17 +664,17 @@
 struct hci_fm_prgm_srv_rsp {
     char    status;
     struct hci_ev_prg_service prg_srv;
-} ;
+} __attribute__((packed));
 
 struct hci_fm_radio_txt_rsp {
     char    status;
     struct hci_ev_radio_text rd_txt;
-} ;
+} __attribute__((packed));
 
 struct hci_fm_af_list_rsp {
     char    status;
     struct hci_ev_af_list rd_txt;
-} ;
+} __attribute__((packed));
 
 struct hci_fm_data_rd_rsp {
     char    data_len;
@@ -763,8 +716,7 @@
     int   freq[MAX_SPUR_FREQ_LIMIT];
     char  rmssi[MAX_SPUR_FREQ_LIMIT];
     char  enable[MAX_SPUR_FREQ_LIMIT];
-} ;
-
+} __attribute__((packed));
 
 /* HCI dev events */
 #define RADIO_HCI_DEV_REG           1
@@ -961,7 +913,6 @@
 int hci_def_data_write(struct hci_fm_def_data_wr_req *arg,
        struct radio_hci_dev *hdev);
 int hci_fm_do_calibration(char *arg, struct radio_hci_dev *hdev);
-int hci_fm_do_calibration(char *arg, struct radio_hci_dev *hdev);
 
 static inline int is_valid_tone(int tone)
 {
@@ -1177,7 +1128,7 @@
         return 0;
 }
 
-struct helium_device {
+struct radio_helium_device {
     int tune_req;
     unsigned int mode;
     short pi;
@@ -1212,7 +1163,7 @@
     struct hci_fm_ch_det_threshold ch_det_threshold;
     struct hci_fm_data_rd_rsp def_data;
     struct hci_fm_blend_table blend_tbl;
-};
+} __attribute__((packed));
 
 #define set_bit(flag, bit_pos)      ((flag) |= (1 << (bit_pos)))
 #define clear_bit(flag, bit_pos)    ((flag) &= (~(1 << (bit_pos))))
@@ -1281,4 +1232,17 @@
 int hci_fm_get_station_dbg_param_req();
 int hci_fm_get_station_cmd_param_req();
 
+struct fm_hal_t {
+    struct radio_helium_device *radio;
+    fm_hal_callbacks_t *jni_cb;
+    void *private_data;
+};
+
+struct fm_interface_t {
+    int (*init)(const fm_hal_callbacks_t *p_cb);
+    int (*set_fm_ctrl)(int opcode, int val);
+    void (*Get_fm_ctrl) (int opcode, int val);
+};
+
 #endif /* __UAPI_RADIO_HCI_CORE_H */
+
diff --git a/helium/radio_helium_hal.c b/helium/radio_helium_hal.c
index e6ab1b1..f22c6f5 100644
--- a/helium/radio_helium_hal.c
+++ b/helium/radio_helium_hal.c
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2015, The Linux Foundation. All rights reserved.
+Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -34,15 +34,13 @@
 #include <utils/Log.h>
 #include "radio-helium-commands.h"
 #include "radio-helium.h"
-#include "fm_hci.h"
+#include "fm_hci_api.h"
 #include <dlfcn.h>
 #include <errno.h>
 
-fm_vendor_callbacks_t *jni_cb;
 int hci_fm_get_signal_threshold();
 int hci_fm_enable_recv_req();
 int hci_fm_mute_mode_req(struct hci_fm_mute_mode_req );
-struct helium_device *radio;
 static int oda_agt;
 static int grp_mask;
 static int rt_plus_carrier = -1;
@@ -59,6 +57,7 @@
 static uint32_t station_param_mask_flag;
 static uint32_t station_dbg_param_mask_flag;
 uint64_t flag;
+struct fm_hal_t *hal = NULL;
 
 #define LOG_TAG "radio_helium"
 static void radio_hci_req_complete(char result)
@@ -80,11 +79,11 @@
         return;
     }
     rsp = (struct hci_fm_conf_rsp *)ev_rsp;
-    jni_cb->thread_evt_cb(0);
+    hal->jni_cb->thread_evt_cb(0);
     radio_hci_req_complete(rsp->status);
-    jni_cb->enabled_cb();
+    hal->jni_cb->enabled_cb();
     if (rsp->status == FM_HC_STATUS_SUCCESS)
-        radio->mode = FM_RECV;
+        hal->radio->mode = FM_RECV;
 }
 
 static void hci_cc_conf_rsp(char *ev_rsp)
@@ -98,7 +97,7 @@
     rsp = (struct hci_fm_conf_rsp *)ev_rsp;
     radio_hci_req_complete(rsp->status);
     if (!rsp->status) {
-        radio->recv_conf = rsp->recv_conf_rsp;
+        hal->radio->recv_conf = rsp->recv_conf_rsp;
     }
 }
 
@@ -111,19 +110,15 @@
         ALOGE("%s:%s, buffer is null\n", LOG_TAG, __func__);
         return;
     }
-    ALOGE("%s:enetred %s calling ", LOG_TAG, __func__);
+    ALOGV("%s++", __func__);
     status = (char) *ev_buff;
     radio_hci_req_complete(status);
-    if (radio->mode == FM_TURNING_OFF) {
-        radio->mode = FM_OFF;
-        jni_cb->disabled_cb();
-        jni_cb->thread_evt_cb(1);
-        //close the userial port and power off the chip
-        ret = fm_power(FM_RADIO_DISABLE);
-        ALOGI("fm power off status = %d", ret);
-        ALOGI("%s:calling fm userial close\n", LOG_TAG );
-        fm_userial_close();
-    //  fm_power(FM_RADIO_DISABLE);
+    if (hal->radio->mode == FM_TURNING_OFF) {
+        ALOGD("%s:calling fm close\n", LOG_TAG );
+        fm_hci_close(hal->private_data);
+        hal->radio->mode = FM_OFF;
+        hal->jni_cb->disabled_cb();
+        hal->jni_cb->thread_evt_cb(1);
     }
 }
 
@@ -152,7 +147,7 @@
     if (status < 0) {
         ALOGE("%s:%s, read rds_grp_cntrs failed status=%d\n", LOG_TAG, __func__,status);
     }
-    jni_cb->rds_grp_cntrs_rsp_cb(&ev_buff[1]);
+    hal->jni_cb->rds_grp_cntrs_rsp_cb(&ev_buff[1]);
 }
 
 static void hci_cc_rds_grp_cntrs_ext_rsp(char *ev_buff)
@@ -168,7 +163,7 @@
     if (status < 0) {
         ALOGE("%s:%s, read rds_grp_cntrs_ext failed status=%d\n", LOG_TAG, __func__,status);
     }
-    jni_cb->rds_grp_cntrs_ext_rsp_cb(&ev_buff[1]);
+    hal->jni_cb->rds_grp_cntrs_ext_rsp_cb(&ev_buff[1]);
 }
 
 static void hci_cc_riva_peek_rsp(char *ev_buff)
@@ -184,7 +179,7 @@
     if (status < 0) {
         ALOGE("%s:%s, peek failed=%d\n", LOG_TAG, __func__, status);
     }
-    jni_cb->fm_peek_rsp_cb(&ev_buff[PEEK_DATA_OFSET]);
+    hal->jni_cb->fm_peek_rsp_cb(&ev_buff[PEEK_DATA_OFSET]);
     radio_hci_req_complete(status);
 }
 
@@ -201,7 +196,7 @@
     if (status < 0) {
         ALOGE("%s:%s,ssbi peek failed=%d\n", LOG_TAG, __func__, status);
     }
-    jni_cb->fm_ssbi_peek_rsp_cb(&ev_buff[PEEK_DATA_OFSET]);
+    hal->jni_cb->fm_ssbi_peek_rsp_cb(&ev_buff[PEEK_DATA_OFSET]);
     radio_hci_req_complete(status);
 }
 
@@ -218,7 +213,7 @@
     if (status != 0) {
         ALOGE("%s:%s,agc gain failed=%d\n", LOG_TAG, __func__, status);
     } else {
-        jni_cb->fm_agc_gain_rsp_cb(&ev_buff[1]);
+        hal->jni_cb->fm_agc_gain_rsp_cb(&ev_buff[1]);
     }
     radio_hci_req_complete(status);
 }
@@ -236,28 +231,28 @@
     if (status != 0) {
         ALOGE("%s:%s,ssbi peek failed=%d\n", LOG_TAG, __func__, status);
     } else {
-        memcpy(&radio->ch_det_threshold, &ev_buff[1],
+        memcpy(&hal->radio->ch_det_threshold, &ev_buff[1],
                         sizeof(struct hci_fm_ch_det_threshold));
         radio_hci_req_complete(status);
 
         if (test_bit(ch_det_th_mask_flag, CMD_CHDET_SINR_TH))
-            val = radio->ch_det_threshold.sinr;
+            val = hal->radio->ch_det_threshold.sinr;
         else if (test_bit(ch_det_th_mask_flag, CMD_CHDET_SINR_SAMPLE))
-            val = radio->ch_det_threshold.sinr_samples;
+            val = hal->radio->ch_det_threshold.sinr_samples;
         else if (test_bit(ch_det_th_mask_flag, CMD_CHDET_INTF_TH_LOW))
-            val = radio->ch_det_threshold.low_th;
+            val = hal->radio->ch_det_threshold.low_th;
         else if (test_bit(ch_det_th_mask_flag, CMD_CHDET_INTF_TH_HIGH))
-            val = radio->ch_det_threshold.high_th;
+            val = hal->radio->ch_det_threshold.high_th;
     }
     clear_all_bit(ch_det_th_mask_flag);
-    jni_cb->fm_get_ch_det_thr_cb(val, status);
+    hal->jni_cb->fm_get_ch_det_thr_cb(val, status);
 }
 
 static void hci_cc_set_ch_det_threshold_rsp(char *ev_buff)
 {
     int status = ev_buff[0];
 
-    jni_cb->fm_set_ch_det_thr_cb(status);
+    hal->jni_cb->fm_set_ch_det_thr_cb(status);
 }
 
 static void hci_cc_sig_threshold_rsp(char *ev_buff)
@@ -272,7 +267,7 @@
     } else {
         val = ev_buff[1];
     }
-    jni_cb->fm_get_sig_thres_cb(val, status);
+    hal->jni_cb->fm_get_sig_thres_cb(val, status);
 }
 
 static void hci_cc_default_data_read_rsp(char *ev_buff)
@@ -287,43 +282,43 @@
     if (status == 0) {
         data_len = ev_buff[1];
         ALOGV("hci_cc_default_data_read_rsp:data_len = %d", data_len);
-        memcpy(&radio->def_data, &ev_buff[1], data_len + sizeof(char));
+        memcpy(&hal->radio->def_data, &ev_buff[1], data_len + sizeof(char));
 
         if (test_bit(def_data_rd_mask_flag, CMD_DEFRD_AF_RMSSI_TH)) {
-            val = radio->def_data.data[AF_RMSSI_TH_OFFSET];
+            val = hal->radio->def_data.data[AF_RMSSI_TH_OFFSET];
         } else if (test_bit(def_data_rd_mask_flag, CMD_DEFRD_AF_RMSSI_SAMPLE)) {
-            val = radio->def_data.data[AF_RMSSI_SAMPLES_OFFSET];
+            val = hal->radio->def_data.data[AF_RMSSI_SAMPLES_OFFSET];
         } else if (test_bit(def_data_rd_mask_flag, CMD_DEFRD_GD_CH_RMSSI_TH)) {
-            val = radio->def_data.data[GD_CH_RMSSI_TH_OFFSET];
+            val = hal->radio->def_data.data[GD_CH_RMSSI_TH_OFFSET];
             if (val > MAX_GD_CH_RMSSI_TH)
                 val -= 256;
         } else if (test_bit(def_data_rd_mask_flag, CMD_DEFRD_SEARCH_ALGO)) {
-            val = radio->def_data.data[SRCH_ALGO_TYPE_OFFSET];
+            val = hal->radio->def_data.data[SRCH_ALGO_TYPE_OFFSET];
         } else if (test_bit(def_data_rd_mask_flag, CMD_DEFRD_SINR_FIRST_STAGE)) {
-            val = radio->def_data.data[SINRFIRSTSTAGE_OFFSET];
+            val = hal->radio->def_data.data[SINRFIRSTSTAGE_OFFSET];
             if (val > MAX_SINR_FIRSTSTAGE)
                 val -= 256;
         } else if (test_bit(def_data_rd_mask_flag, CMD_DEFRD_RMSSI_FIRST_STAGE)) {
-            val = radio->def_data.data[RMSSIFIRSTSTAGE_OFFSET];
+            val = hal->radio->def_data.data[RMSSIFIRSTSTAGE_OFFSET];
         } else if (test_bit(def_data_rd_mask_flag, CMD_DEFRD_CF0TH12)) {
-            val = (radio->def_data.data[CF0TH12_BYTE1_OFFSET] |
-                    (radio->def_data.data[CF0TH12_BYTE2_OFFSET] << 8));
+            val = (hal->radio->def_data.data[CF0TH12_BYTE1_OFFSET] |
+                    (hal->radio->def_data.data[CF0TH12_BYTE2_OFFSET] << 8));
         } else if (test_bit(def_data_rd_mask_flag, CMD_DEFRD_TUNE_POWER)) {
         } else if (test_bit(def_data_rd_mask_flag, CMD_DEFRD_REPEATCOUNT)) {
-            val = radio->def_data.data[RX_REPEATE_BYTE_OFFSET];
+            val = hal->radio->def_data.data[RX_REPEATE_BYTE_OFFSET];
         }
     } else {
         ALOGE("%s: Error: Status= 0x%x", __func__, status);
     }
     clear_all_bit(def_data_rd_mask_flag);
-    jni_cb->fm_def_data_read_cb(val, status);
+    hal->jni_cb->fm_def_data_read_cb(val, status);
 }
 
 static void hci_cc_default_data_write_rsp(char *ev_buff)
 {
     int status = ev_buff[0];
 
-    jni_cb->fm_def_data_write_cb(status);
+    hal->jni_cb->fm_def_data_write_cb(status);
 }
 
 static void hci_cc_get_blend_tbl_rsp(char *ev_buff)
@@ -339,7 +334,7 @@
     if (status != 0) {
         ALOGE("%s: status = 0x%x", LOG_TAG, status);
     } else {
-        memcpy(&radio->blend_tbl, &ev_buff[1],
+        memcpy(&hal->radio->blend_tbl, &ev_buff[1],
                 sizeof(struct hci_fm_blend_table));
 
         ALOGE("hci_cc_get_blend_tbl_rsp: data");
@@ -347,20 +342,20 @@
         for (i = 0; i < 8; i++)
             ALOGE("data[%d] = 0x%x", i, ev_buff[1 + i]);
         if (test_bit(blend_tbl_mask_flag, CMD_BLENDTBL_SINR_HI)) {
-            val = radio->blend_tbl.BlendSinrHi;
+            val = hal->radio->blend_tbl.BlendSinrHi;
         } else if (test_bit(blend_tbl_mask_flag, CMD_BLENDTBL_RMSSI_HI)) {
-            val = radio->blend_tbl.BlendRmssiHi;
+            val = hal->radio->blend_tbl.BlendRmssiHi;
         }
     }
     clear_all_bit(blend_tbl_mask_flag);
-    jni_cb->fm_get_blend_cb(val, status);
+    hal->jni_cb->fm_get_blend_cb(val, status);
 }
 
 static void hci_cc_set_blend_tbl_rsp(char *ev_buff)
 {
     int status = ev_buff[0];
 
-    jni_cb->fm_set_blend_cb(status);
+    hal->jni_cb->fm_set_blend_cb(status);
 }
 
 static void hci_cc_station_rsp(char *ev_buff)
@@ -368,17 +363,17 @@
     int val, status = ev_buff[0];
 
     if (status == FM_HC_STATUS_SUCCESS) {
-        memcpy(&radio->fm_st_rsp.station_rsp.station_freq, &ev_buff[1],
+        memcpy(&hal->radio->fm_st_rsp.station_rsp.station_freq, &ev_buff[1],
                 sizeof(struct hci_fm_station_rsp) - sizeof(char));
         if (test_bit(station_param_mask_flag, CMD_STNPARAM_RSSI)) {
-                val = radio->fm_st_rsp.station_rsp.rssi;
+                val = hal->radio->fm_st_rsp.station_rsp.rssi;
         } else if (test_bit(station_param_mask_flag, CMD_STNPARAM_SINR)) {
-            val = radio->fm_st_rsp.station_rsp.sinr;
+            val = hal->radio->fm_st_rsp.station_rsp.sinr;
         }
     }
     ALOGE("hci_cc_station_rsp: val =%x, status = %x", val, status);
 
-    jni_cb->fm_get_station_param_cb(val, status);
+    hal->jni_cb->fm_get_station_param_cb(val, status);
     clear_all_bit(station_param_mask_flag);
 }
 
@@ -387,16 +382,16 @@
     int val, status = ev_buff[0];
 
     if (status == FM_HC_STATUS_SUCCESS) {
-        memcpy(&radio->st_dbg_param, &ev_buff[1],
+        memcpy(&hal->radio->st_dbg_param, &ev_buff[1],
                 sizeof(struct hci_fm_dbg_param_rsp));
         if (test_bit(station_dbg_param_mask_flag, CMD_STNDBGPARAM_INFDETOUT)) {
-            val = radio->st_dbg_param.in_det_out;
+            val = hal->radio->st_dbg_param.in_det_out;
         } else if (test_bit(station_dbg_param_mask_flag, CMD_STNDBGPARAM_IOVERC)) {
-            val = radio->st_dbg_param.io_verc;
+            val = hal->radio->st_dbg_param.io_verc;
         }
     }
     ALOGE("hci_cc_dbg_param_rsp: val =%x, status = %x", val, status);
-    jni_cb->fm_get_station_debug_param_cb(val, status);
+    hal->jni_cb->fm_get_station_debug_param_cb(val, status);
     clear_all_bit(station_dbg_param_mask_flag);
 }
 
@@ -549,27 +544,29 @@
 static inline void hci_ev_tune_status(char *buff)
 {
 
-    memcpy(&radio->fm_st_rsp.station_rsp, &buff[0],
+    memcpy(&hal->radio->fm_st_rsp.station_rsp, &buff[0],
                                sizeof(struct hci_ev_tune_status));
-    jni_cb->tune_cb(radio->fm_st_rsp.station_rsp.station_freq);
+    char *freq = &hal->radio->fm_st_rsp.station_rsp.station_freq;
+    ALOGD("freq = %d", hal->radio->fm_st_rsp.station_rsp.station_freq);
+    hal->jni_cb->tune_cb(hal->radio->fm_st_rsp.station_rsp.station_freq);
 
-    //    if (radio->fm_st_rsp.station_rsp.serv_avble)
+    //    if (hal->radio->fm_st_rsp.station_rsp.serv_avble)
           // todo callback for threshould
 
-    if (radio->fm_st_rsp.station_rsp.stereo_prg)
-        jni_cb->stereo_status_cb(true);
-    else if (radio->fm_st_rsp.station_rsp.stereo_prg == 0)
-        jni_cb->stereo_status_cb(false);
+    if (hal->radio->fm_st_rsp.station_rsp.stereo_prg)
+        hal->jni_cb->stereo_status_cb(true);
+    else if (hal->radio->fm_st_rsp.station_rsp.stereo_prg == 0)
+        hal->jni_cb->stereo_status_cb(false);
 
-    if (radio->fm_st_rsp.station_rsp.rds_sync_status)
-        jni_cb->rds_avail_status_cb(true);
+    if (hal->radio->fm_st_rsp.station_rsp.rds_sync_status)
+        hal->jni_cb->rds_avail_status_cb(true);
     else
-        jni_cb->rds_avail_status_cb(false);
+        hal->jni_cb->rds_avail_status_cb(false);
 }
 
 static inline void hci_ev_search_next(char *buff)
 {
-    jni_cb->scan_next_cb();
+    hal->jni_cb->scan_next_cb();
 }
 
 static inline void hci_ev_stereo_status(char *buff)
@@ -582,9 +579,9 @@
     }
     st_status =  buff[0];
     if (st_status)
-        jni_cb->stereo_status_cb(true);
+        hal->jni_cb->stereo_status_cb(true);
     else
-        jni_cb->stereo_status_cb(false);
+        hal->jni_cb->stereo_status_cb(false);
 }
 
 static void hci_ev_rds_lock_status(char *buff)
@@ -599,9 +596,9 @@
     rds_status = buff[0];
 
     if (rds_status)
-        jni_cb->rds_avail_status_cb(true);
+        hal->jni_cb->rds_avail_status_cb(true);
     else
-        jni_cb->rds_avail_status_cb(false);
+        hal->jni_cb->rds_avail_status_cb(false);
 }
 
 static inline void hci_ev_program_service(char *buff)
@@ -625,7 +622,7 @@
     memcpy(data+RDS_OFFSET, &buff[RDS_PS_DATA_OFFSET], len-RDS_OFFSET);
 
     ALOGE("SSK call ps-callback");
-    jni_cb->ps_update_cb(data);
+    hal->jni_cb->ps_update_cb(data);
 
     free(data);
 }
@@ -658,7 +655,7 @@
     memcpy(data+RDS_OFFSET, &buff[RDS_OFFSET], len);
     data[len+RDS_OFFSET] = 0x00;
 
-    jni_cb->rt_update_cb(data);
+    hal->jni_cb->rt_update_cb(data);
     free(data);
 }
 
@@ -679,7 +676,7 @@
     }
     memcpy(&ev.af_list[0], &buff[AF_LIST_OFFSET],
                                         ev.af_size * sizeof(int));
-    jni_cb->af_list_update_cb(&ev);
+    hal->jni_cb->af_list_update_cb(&ev);
 }
 
 static inline void hci_ev_search_compl(char *buff)
@@ -688,8 +685,8 @@
         ALOGE("%s:%s,buffer is null\n", LOG_TAG, __func__);
         return;
     }
-    radio->search_on = 0;
-    jni_cb->seek_cmpl_cb(radio->fm_st_rsp.station_rsp.station_freq);
+    hal->radio->search_on = 0;
+    hal->jni_cb->seek_cmpl_cb(hal->radio->fm_st_rsp.station_rsp.station_freq);
 }
 
 static inline void hci_ev_srch_st_list_compl(char *buff)
@@ -720,7 +717,7 @@
             cnt += PARAMS_PER_STATION, stn_num++) {
 
         abs_freq = *((int *)&buff[cnt]);
-        rel_freq = abs_freq - radio->recv_conf.band_low_limit;
+        rel_freq = abs_freq - hal->radio->recv_conf.band_low_limit;
         rel_freq = (rel_freq * 20) / KHZ_TO_MHZ;
 
         ev->rel_freq[stn_num].rel_freq_lsb = GET_LSB(rel_freq);
@@ -728,7 +725,7 @@
     }
 
     len = ev->num_stations_found * 2 + sizeof(ev->num_stations_found);
-    jni_cb->srch_list_cb((char*)ev);
+    hal->jni_cb->srch_list_cb((char*)ev);
     free(ev);
 }
 
@@ -772,7 +769,7 @@
         data[4] = buff[3];
         memcpy(&data[RDS_OFFSET], &buff[4], len-RDS_OFFSET);
         // data[len] = 0x00;
-        jni_cb->rt_plus_update_cb(data);
+        hal->jni_cb->rt_plus_update_cb(data);
         free(data);
      } else {
         ALOGE("%s:memory allocation failed\n", LOG_TAG);
@@ -793,8 +790,7 @@
         data[3] = buff[RDS_PID_HIGHER];
         data[4] = buff[3];
         memcpy(&data[RDS_OFFSET], &buff[4], len-RDS_OFFSET);
-        // data[len] = 0x00;
-        jni_cb->ext_country_code_cb(data);
+        hal->jni_cb->ext_country_code_cb(data);
         free(data);
     } else {
         ALOGE("%s:memory allocation failed\n", LOG_TAG);
@@ -813,7 +809,7 @@
         data[1] = utf_8_flag;
         data[2] = formatting_dir;
         memcpy((data + 3), ert_buf, ert_len);
-        jni_cb->ert_update_cb(data);
+        hal->jni_cb->ert_update_cb(data);
         free(data);
     }
 }
@@ -821,9 +817,9 @@
 static void hci_ev_hw_error(char *buff)
 {
    ALOGE("%s:%s: start", LOG_TAG, __func__);
-   jni_cb->disabled_cb();
-   jni_cb->thread_evt_cb(1);
-   fm_userial_close();
+   fm_hci_close(hal->private_data);
+   hal->jni_cb->disabled_cb();
+   hal->jni_cb->thread_evt_cb(1);
 }
 
 static void hci_buff_ert(struct rds_grp_data *rds_buf)
@@ -917,7 +913,7 @@
              formatting_dir = EXTRACT_BIT(temp.rdsBlk[2].rdsLsb,
                                                ERT_FORMAT_DIR_BIT);
              if (ert_carrier != agt)
-                 jni_cb->oda_update_cb();
+                 hal->jni_cb->oda_update_cb();
              ert_carrier = agt;
              break;
         case RT_PLUS_AID:
@@ -935,7 +931,7 @@
              rt_ert_flag = EXTRACT_BIT(temp.rdsBlk[2].rdsMsb,
                                               RT_ERT_FLAG_BIT);
              if (rt_plus_carrier != agt)
-                 jni_cb->oda_update_cb();
+                 hal->jni_cb->oda_update_cb();
              rt_plus_carrier = agt;
              break;
         default:
@@ -959,65 +955,65 @@
     char evt;
 
     ALOGE("%s:%s: Received %d bytes of HCI EVENT PKT from Controller", LOG_TAG,
-                                      __func__, ((FM_EVT_HDR *)evt_buf)->evt_len);
-    evt = ((FM_EVT_HDR *)evt_buf)->evt_code;
+                                      __func__, ((struct fm_event_header_t *)evt_buf)->evt_len);
+    evt = ((struct fm_event_header_t *)evt_buf)->evt_code;
     ALOGE("%s:evt: %d", LOG_TAG, evt);
 
     switch(evt) {
     case HCI_EV_TUNE_STATUS:
-        hci_ev_tune_status(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_tune_status(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_SEARCH_PROGRESS:
     case HCI_EV_SEARCH_RDS_PROGRESS:
     case HCI_EV_SEARCH_LIST_PROGRESS:
-        hci_ev_search_next(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_search_next(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_STEREO_STATUS:
-        hci_ev_stereo_status(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_stereo_status(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_RDS_LOCK_STATUS:
-        hci_ev_rds_lock_status(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_rds_lock_status(((struct fm_event_header_t *)evt_buf)->params);
         break;
 /*    case HCI_EV_SERVICE_AVAILABLE:
         hci_ev_service_available(hdev, skb);
         break; */
     case HCI_EV_RDS_RX_DATA:
-        hci_ev_raw_rds_group_data(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_raw_rds_group_data(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_PROGRAM_SERVICE:
-        hci_ev_program_service(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_program_service(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_RADIO_TEXT:
-        hci_ev_radio_text(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_radio_text(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_FM_AF_LIST:
-        hci_ev_af_list(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_af_list(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_CMD_COMPLETE:
         ALOGE("%s:%s: Received HCI_EV_CMD_COMPLETE", LOG_TAG, __func__);
-        hci_cmd_complete_event(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_cmd_complete_event(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_CMD_STATUS:
-        hci_cmd_status_event(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_cmd_status_event(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_SEARCH_COMPLETE:
     case HCI_EV_SEARCH_RDS_COMPLETE:
-        hci_ev_search_compl(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_search_compl(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_SEARCH_LIST_COMPLETE:
-        hci_ev_srch_st_list_compl(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_srch_st_list_compl(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_RADIO_TEXT_PLUS_ID:
-        hci_ev_rt_plus_id(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_rt_plus_id(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_RADIO_TEXT_PLUS_TAG:
-        hci_ev_rt_plus_tag(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_rt_plus_tag(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_EXT_COUNTRY_CODE:
-        hci_ev_ext_country_code(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_ext_country_code(((struct fm_event_header_t *)evt_buf)->params);
         break;
     case HCI_EV_HW_ERR_EVENT:
-        hci_ev_hw_error(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        hci_ev_hw_error(((struct fm_event_header_t *)evt_buf)->params);
         break;
     default:
         break;
@@ -1025,10 +1021,10 @@
 }
 
 /* 'evt_buf' contains the event received from Controller */
-int fm_evt_notify(char *evt_buf)
+int process_event(void *hal, unsigned char *evt_buf)
 {
     ALOGI("%s: %s: Received event notification from FM-HCI thread. EVT CODE: %d ",
-                            LOG_TAG,  __func__, ((FM_EVT_HDR *)evt_buf)->evt_code);
+                            LOG_TAG,  __func__, ((struct fm_event_header_t *)evt_buf)->evt_code);
     radio_hci_event_packet(evt_buf);
     return 0;
 }
@@ -1040,9 +1036,9 @@
     int saved_val;
     int dir;
 
-    srch = radio->g_search_mode & SRCH_MODE;
-    saved_val = radio->search_on;
-    radio->search_on = on;
+    srch = hal->radio->g_search_mode & SRCH_MODE;
+    saved_val = hal->radio->search_on;
+    hal->radio->search_on = on;
     if (direct)
         dir = SRCH_DIR_UP;
     else
@@ -1052,24 +1048,24 @@
         switch (srch) {
         case SCAN_FOR_STRONG:
         case SCAN_FOR_WEAK:
-            radio->srch_st_list.srch_list_dir = dir;
-            radio->srch_st_list.srch_list_mode = srch;
-            retval = helium_search_list(&radio->srch_st_list);
+            hal->radio->srch_st_list.srch_list_dir = dir;
+            hal->radio->srch_st_list.srch_list_mode = srch;
+            retval = helium_search_list(&hal->radio->srch_st_list);
             break;
         case RDS_SEEK_PTY:
         case RDS_SCAN_PTY:
         case RDS_SEEK_PI:
             srch = srch - SEARCH_RDS_STNS_MODE_OFFSET;
-            radio->srch_rds.srch_station.srch_mode = srch;
-            radio->srch_rds.srch_station.srch_dir = dir;
-            radio->srch_rds.srch_station.scan_time = radio->g_scan_time;
-            retval = helium_search_rds_stations(&radio->srch_rds);
+            hal->radio->srch_rds.srch_station.srch_mode = srch;
+            hal->radio->srch_rds.srch_station.srch_dir = dir;
+            hal->radio->srch_rds.srch_station.scan_time = hal->radio->g_scan_time;
+            retval = helium_search_rds_stations(&hal->radio->srch_rds);
             break;
         default:
-            radio->srch_st.srch_mode = srch;
-            radio->srch_st.scan_time = radio->g_scan_time;
-            radio->srch_st.srch_dir = dir;
-            retval = helium_search_stations(&radio->srch_st);
+            hal->radio->srch_st.srch_mode = srch;
+            hal->radio->srch_st.scan_time = hal->radio->g_scan_time;
+            hal->radio->srch_st.srch_dir = dir;
+            retval = helium_search_stations(&hal->radio->srch_st);
             break;
         }
     } else {
@@ -1077,7 +1073,7 @@
     }
 
     if (retval < 0)
-        radio->search_on = saved_val;
+        hal->radio->search_on = saved_val;
     return retval;
 }
 
@@ -1086,12 +1082,12 @@
     int retval;
     int saved_val;
 
-    saved_val = radio->region;
-    radio->region = req_region;
+    saved_val = hal->radio->region;
+    hal->radio->region = req_region;
 
-    retval = hci_fm_set_recv_conf_req(&radio->recv_conf);
+    retval = hci_fm_set_recv_conf_req(&hal->radio->recv_conf);
     if (retval < 0)
-        radio->region = saved_val;
+        hal->radio->region = saved_val;
     return retval;
 }
 
@@ -1100,10 +1096,10 @@
     int rds_grps_proc = 0x00;
     int retval = 0;
 
-    if (radio->power_mode != lp_mode) {
+    if (hal->radio->power_mode != lp_mode) {
        if (lp_mode) {
-           radio->event_mask = 0x00;
-           if (radio->af_jump_bit)
+           hal->radio->event_mask = 0x00;
+           if (hal->radio->af_jump_bit)
                rds_grps_proc = 0x00 | AF_JUMP_ENABLE;
            else
                rds_grps_proc = 0x00;
@@ -1112,52 +1108,78 @@
                ALOGE("%s:Disable RDS failed", LOG_TAG);
                return retval;
            }
-           retval = helium_set_event_mask_req(radio->event_mask);
+           retval = helium_set_event_mask_req(hal->radio->event_mask);
        } else {
-           radio->event_mask = SIG_LEVEL_INTR | RDS_SYNC_INTR | AUDIO_CTRL_INTR;
-           retval = helium_set_event_mask_req(radio->event_mask);
+           hal->radio->event_mask = SIG_LEVEL_INTR | RDS_SYNC_INTR | AUDIO_CTRL_INTR;
+           retval = helium_set_event_mask_req(hal->radio->event_mask);
            if (retval < 0) {
                ALOGE("%s:Enable Async events failed", LOG_TAG);
                return retval;
            }
-           radio->g_rds_grp_proc_ps = 0x000000FF;
-           retval = helium_rds_grp_process_req(radio->g_rds_grp_proc_ps);
+           hal->radio->g_rds_grp_proc_ps = 0x000000FF;
+           retval = helium_rds_grp_process_req(hal->radio->g_rds_grp_proc_ps);
        }
-       radio->power_mode = lp_mode;
+       hal->radio->power_mode = lp_mode;
     }
     return retval;
 }
 
 
 /* Callback function to be registered with FM-HCI for event notification */
-static fm_hal_cb hal_cb = {
-    fm_evt_notify
+static struct fm_hci_callbacks_t hal_cb = {
+    process_event
 };
 
-int hal_init( fm_vendor_callbacks_t *p_cb)
+int hal_init(fm_hal_callbacks_t *cb)
 {
-    int ret = -1;
+    int ret = -FM_HC_STATUS_FAIL;
+    fm_hci_hal_t hci_hal;
 
-     radio = malloc(sizeof(struct helium_device));
-     if (!radio) {
-         ALOGE("%s:Failed to allocate memory for device", LOG_TAG);
-         return ret;
-     }
-    /* Save the JNI callback functions */
-    jni_cb = p_cb;
+    ALOGD("++%s", __func__);
+
+    memset(&hci_hal, 0, sizeof(fm_hci_hal_t));
+
+    hal = malloc(sizeof(struct fm_hal_t));
+    if (!hal) {
+        ALOGE("%s:Failed to allocate memory", __func__);
+        ret = -FM_HC_STATUS_NOMEM;
+        goto out;
+    }
+    memset(hal, 0, sizeof(struct fm_hal_t));
+    hal->jni_cb = cb;
+    hal->radio = malloc(sizeof(struct radio_helium_device));
+    if (!hal->radio) {
+        ALOGE("%s:Failed to allocate memory for device", __func__);
+        goto out;
+    }
+
+    memset(hal->radio, 0,  sizeof(struct radio_helium_device));
+
+    hci_hal.hal = hal;
+    hci_hal.cb = &hal_cb;
 
     /* Initialize the FM-HCI */
-    ALOGE("%s:%s: Initializing the event notification func with FM-HCI", LOG_TAG, __func__);
-    ret = fm_hci_init(&hal_cb);
+    ret = fm_hci_init(&hci_hal);
+    if (ret != FM_HC_STATUS_SUCCESS) {
+        ALOGE("%s:fm_hci_init failed", __func__);
+        goto out;
+    }
+    hal->private_data = hci_hal.hci;
 
-    ALOGE("%s:%s: Turning FM ON...", LOG_TAG, __func__);
-    ret = fm_power(FM_RADIO_ENABLE);
+    return FM_HC_STATUS_SUCCESS;
 
-    ALOGE("%s:%s: Firmware download and HCI Initialization in-progress...", LOG_TAG, __func__);
-    /* TODO : Start the preload timer */
-    open_serial_port();
-    pthread_mutex_init(&fm_hal, NULL);
-    return 0;
+out:
+    ALOGV("--%s", __func__);
+    if (hal) {
+        if (hal->radio) {
+            free(hal->radio);
+            hal->radio = NULL;
+        }
+        hal->jni_cb = NULL;
+        free(hal);
+        hal = NULL;
+    }
+    return ret;
 }
 
 /* Called by the JNI for performing the FM operations */
@@ -1170,27 +1192,31 @@
     char *data;
     struct hci_fm_def_data_wr_req def_data_wrt;
 
-    ALOGE("%s:cmd: %x, val: %d",LOG_TAG, cmd, val);
+    if (!hal) {
+        ALOGE("%s:ALERT: command sent before hal init", __func__);
+        return -FM_HC_STATUS_FAIL;
+    }
+    ALOGD("%s:cmd: %x, val: %d",LOG_TAG, cmd, val);
 
     switch (cmd) {
     case HCI_FM_HELIUM_AUDIO_MUTE:
-        saved_val = radio->mute_mode.hard_mute;
-        radio->mute_mode.hard_mute = val;
-        ret = hci_fm_mute_mode_req(radio->mute_mode);
+        saved_val = hal->radio->mute_mode.hard_mute;
+        hal->radio->mute_mode.hard_mute = val;
+        ret = hci_fm_mute_mode_req(hal->radio->mute_mode);
         if (ret < 0) {
             ALOGE("%s:Error while set FM hard mute %d", LOG_TAG, ret);
-            radio->mute_mode.hard_mute = saved_val;
+            hal->radio->mute_mode.hard_mute = saved_val;
         }
         break;
     case HCI_FM_HELIUM_SRCHMODE:
         if (is_valid_srch_mode(val))
-            radio->g_search_mode = val;
+            hal->radio->g_search_mode = val;
         else
             ret = -EINVAL;
         break;
     case HCI_FM_HELIUM_SCANDWELL:
         if (is_valid_scan_dwell_prd(val))
-            radio->g_scan_time = val;
+            hal->radio->g_scan_time = val;
         else
             ret = -EINVAL;
         break;
@@ -1203,7 +1229,7 @@
             ret = hci_fm_enable_recv_req();
             break;
         case FM_OFF:
-            radio->mode = FM_TURNING_OFF;
+            hal->radio->mode = FM_TURNING_OFF;
             hci_fm_disable_recv_req();
             break;
         default:
@@ -1223,84 +1249,84 @@
         break;
     case HCI_FM_HELIUM_SRCH_PTY:
         if (is_valid_pty(val)) {
-            radio->srch_rds.srch_pty = val;
-            radio->srch_st_list.srch_pty = val;
+            hal->radio->srch_rds.srch_pty = val;
+            hal->radio->srch_st_list.srch_pty = val;
         } else {
             ret = -EINVAL;
         }
          break;
     case HCI_FM_HELIUM_SRCH_PI:
          if (is_valid_pi(val))
-             radio->srch_rds.srch_pi = val;
+             hal->radio->srch_rds.srch_pi = val;
          else
              ret = -EINVAL;
          break;
     case HCI_FM_HELIUM_SRCH_CNT:
          if (is_valid_srch_station_cnt(val))
-             radio->srch_st_list.srch_list_max = val;
+             hal->radio->srch_st_list.srch_list_max = val;
          else
              ret = -EINVAL;
          break;
     case HCI_FM_HELIUM_SPACING:
-         saved_val = radio->recv_conf.ch_spacing;
-         radio->recv_conf.ch_spacing = val;
-         ret = hci_fm_set_recv_conf_req(&radio->recv_conf);
+         saved_val = hal->radio->recv_conf.ch_spacing;
+         hal->radio->recv_conf.ch_spacing = val;
+         ret = hci_fm_set_recv_conf_req(&hal->radio->recv_conf);
          if (ret < 0) {
              ALOGE("%s:Error in setting channel spacing", LOG_TAG);
-             radio->recv_conf.ch_spacing = saved_val;
+             hal->radio->recv_conf.ch_spacing = saved_val;
              goto end;
         }
         break;
     case HCI_FM_HELIUM_EMPHASIS:
-         saved_val = radio->recv_conf.emphasis;
-         radio->recv_conf.emphasis = val;
-         ret = hci_fm_set_recv_conf_req(&radio->recv_conf);
+         saved_val = hal->radio->recv_conf.emphasis;
+         hal->radio->recv_conf.emphasis = val;
+         ret = hci_fm_set_recv_conf_req(&hal->radio->recv_conf);
          if (ret < 0) {
              ALOGE("%s:Error in setting emphasis", LOG_TAG);
-             radio->recv_conf.emphasis = saved_val;
+             hal->radio->recv_conf.emphasis = saved_val;
              goto end;
          }
          break;
     case HCI_FM_HELIUM_RDS_STD:
-         saved_val = radio->recv_conf.rds_std;
-         radio->recv_conf.rds_std = val;
-         ret = hci_fm_set_recv_conf_req(&radio->recv_conf);
+         saved_val = hal->radio->recv_conf.rds_std;
+         hal->radio->recv_conf.rds_std = val;
+         ret = hci_fm_set_recv_conf_req(&hal->radio->recv_conf);
          if (ret < 0) {
              ALOGE("%s:Error in rds_std", LOG_TAG);
-             radio->recv_conf.rds_std = saved_val;
+             hal->radio->recv_conf.rds_std = saved_val;
              goto end;
          }
          break;
     case HCI_FM_HELIUM_RDSON:
-         saved_val = radio->recv_conf.rds_std;
-         radio->recv_conf.rds_std = val;
-         ret = hci_fm_set_recv_conf_req(&radio->recv_conf);
+         saved_val = hal->radio->recv_conf.rds_std;
+         hal->radio->recv_conf.rds_std = val;
+         ret = hci_fm_set_recv_conf_req(&hal->radio->recv_conf);
          if (ret < 0) {
              ALOGE("%s:Error in rds_std", LOG_TAG);
-             radio->recv_conf.rds_std = saved_val;
+             hal->radio->recv_conf.rds_std = saved_val;
              goto end;
          }
          break;
     case HCI_FM_HELIUM_RDSGROUP_MASK:
-         saved_val = radio->rds_grp.rds_grp_enable_mask;
+         saved_val = hal->radio->rds_grp.rds_grp_enable_mask;
          grp_mask = (grp_mask | oda_agt | val);
-         radio->rds_grp.rds_grp_enable_mask = grp_mask;
-         radio->rds_grp.rds_buf_size = 1;
-         radio->rds_grp.en_rds_change_filter = 0;
-         ret = helium_rds_grp_mask_req(&radio->rds_grp);
+         hal->radio->rds_grp.rds_grp_enable_mask = grp_mask;
+         hal->radio->rds_grp.rds_buf_size = 1;
+         hal->radio->rds_grp.en_rds_change_filter = 0;
+         ret = helium_rds_grp_mask_req(&hal->radio->rds_grp);
          if (ret < 0) {
              ALOGE("%s:error in setting group mask\n", LOG_TAG);
-             radio->rds_grp.rds_grp_enable_mask = saved_val;
+             hal->radio->rds_grp.rds_grp_enable_mask = saved_val;
              goto end;
         }
         break;
     case HCI_FM_HELIUM_RDSGROUP_PROC:
-         saved_val = radio->g_rds_grp_proc_ps;
-         rds_grps_proc = radio->g_rds_grp_proc_ps | (val & 0xFF);
-         radio->g_rds_grp_proc_ps = rds_grps_proc;
-         ret = helium_rds_grp_process_req(radio->g_rds_grp_proc_ps);
+         saved_val = hal->radio->g_rds_grp_proc_ps;
+         rds_grps_proc = hal->radio->g_rds_grp_proc_ps | (val & 0xFF);
+         hal->radio->g_rds_grp_proc_ps = rds_grps_proc;
+         ret = helium_rds_grp_process_req(hal->radio->g_rds_grp_proc_ps);
          if (ret < 0) {
-             radio->g_rds_grp_proc_ps = saved_val;
+             hal->radio->g_rds_grp_proc_ps = saved_val;
              goto end;
          }
          break;
@@ -1309,7 +1335,7 @@
          ALOGD("%s: rds_grp counter read  value=%d ", LOG_TAG,val);
          ret = hci_fm_get_rds_grpcounters_req(val);
          if (ret < 0) {
-             radio->g_rds_grp_proc_ps = saved_val;
+             hal->radio->g_rds_grp_proc_ps = saved_val;
              goto end;
          }
          break;
@@ -1318,7 +1344,7 @@
          ALOGD("%s: rds_grp counter read  value=%d ", LOG_TAG,val);
          ret = hci_fm_get_rds_grpcounters_ext_req(val);
          if (ret < 0) {
-            radio->g_rds_grp_proc_ps = saved_val;
+            hal->radio->g_rds_grp_proc_ps = saved_val;
             goto end ;
          }
          break;
@@ -1332,28 +1358,28 @@
          break;
 
     case HCI_FM_HELIUM_RDSD_BUF:
-         radio->rds_grp.rds_buf_size = val;
+         hal->radio->rds_grp.rds_buf_size = val;
          break;
     case HCI_FM_HELIUM_PSALL:
-         saved_val = radio->g_rds_grp_proc_ps;
+         saved_val = hal->radio->g_rds_grp_proc_ps;
          rds_grps_proc = (val << RDS_CONFIG_OFFSET);
-         radio->g_rds_grp_proc_ps |= rds_grps_proc;
-         ret = helium_rds_grp_process_req(radio->g_rds_grp_proc_ps);
+         hal->radio->g_rds_grp_proc_ps |= rds_grps_proc;
+         ret = helium_rds_grp_process_req(hal->radio->g_rds_grp_proc_ps);
          if (ret < 0) {
-             radio->g_rds_grp_proc_ps = saved_val;
+             hal->radio->g_rds_grp_proc_ps = saved_val;
              goto end;
         }
         break;
     case HCI_FM_HELIUM_AF_JUMP:
-        saved_val = radio->g_rds_grp_proc_ps;
-        radio->g_rds_grp_proc_ps &= ~(1 << RDS_AF_JUMP_OFFSET);
-        radio->af_jump_bit = val;
+        saved_val = hal->radio->g_rds_grp_proc_ps;
+        hal->radio->g_rds_grp_proc_ps &= ~(1 << RDS_AF_JUMP_OFFSET);
+        hal->radio->af_jump_bit = val;
         rds_grps_proc = 0x00;
         rds_grps_proc = (val << RDS_AF_JUMP_OFFSET);
-        radio->g_rds_grp_proc_ps |= rds_grps_proc;
-        ret = helium_rds_grp_process_req(radio->g_rds_grp_proc_ps);
+        hal->radio->g_rds_grp_proc_ps |= rds_grps_proc;
+        ret = helium_rds_grp_process_req(hal->radio->g_rds_grp_proc_ps);
         if (ret < 0) {
-            radio->g_rds_grp_proc_ps = saved_val;
+            hal->radio->g_rds_grp_proc_ps = saved_val;
             goto end;
         }
         break;
@@ -1367,15 +1393,15 @@
             ALOGE("%s:Set Antenna failed retval = %x", LOG_TAG, ret);
             goto end;
         }
-        radio->g_antenna =  val;
+        hal->radio->g_antenna =  val;
         break;
     case HCI_FM_HELIUM_SOFT_MUTE:
-         saved_val = radio->mute_mode.soft_mute;
-         radio->mute_mode.soft_mute = val;
-         ret = helium_set_fm_mute_mode_req(&radio->mute_mode);
+         saved_val = hal->radio->mute_mode.soft_mute;
+         hal->radio->mute_mode.soft_mute = val;
+         ret = helium_set_fm_mute_mode_req(&hal->radio->mute_mode);
          if (ret < 0) {
              ALOGE("%s:Error while setting FM soft mute %d", LOG_TAG, ret);
-             radio->mute_mode.soft_mute = saved_val;
+             hal->radio->mute_mode.soft_mute = saved_val;
              goto end;
          }
          break;
@@ -1386,21 +1412,21 @@
         helium_search_req(1, val);
         break;
     case HCI_FM_HELIUM_UPPER_BAND:
-        radio->recv_conf.band_high_limit = val;
+        hal->radio->recv_conf.band_high_limit = val;
         break;
     case HCI_FM_HELIUM_LOWER_BAND:
-        radio->recv_conf.band_low_limit = val;
+        hal->radio->recv_conf.band_low_limit = val;
         break;
     case HCI_FM_HELIUM_AUDIO_MODE:
-        radio->stereo_mode.stereo_mode = ~val;
-        hci_set_fm_stereo_mode_req(&radio->stereo_mode);
+        hal->radio->stereo_mode.stereo_mode = ~val;
+        hci_set_fm_stereo_mode_req(&hal->radio->stereo_mode);
         break;
     case HCI_FM_HELIUM_RIVA_ACCS_ADDR:
-        radio->riva_data_req.cmd_params.start_addr = val;
+        hal->radio->riva_data_req.cmd_params.start_addr = val;
         break;
     case HCI_FM_HELIUM_RIVA_ACCS_LEN:
         if (is_valid_peek_len(val)) {
-            radio->riva_data_req.cmd_params.length = val;
+            hal->radio->riva_data_req.cmd_params.length = val;
         } else {
             ret = -1;
             ALOGE("%s: riva access len is not valid\n", LOG_TAG);
@@ -1408,15 +1434,15 @@
         }
         break;
     case HCI_FM_HELIUM_RIVA_PEEK:
-        radio->riva_data_req.cmd_params.subopcode = RIVA_PEEK_OPCODE;
-        val = hci_peek_data(&radio->riva_data_req.cmd_params);
+        hal->radio->riva_data_req.cmd_params.subopcode = RIVA_PEEK_OPCODE;
+        val = hci_peek_data(&hal->radio->riva_data_req.cmd_params);
         break;
     case HCI_FM_HELIUM_RIVA_POKE:
-         if (radio->riva_data_req.cmd_params.length <=
+         if (hal->radio->riva_data_req.cmd_params.length <=
                     MAX_RIVA_PEEK_RSP_SIZE) {
-             radio->riva_data_req.cmd_params.subopcode =
+             hal->radio->riva_data_req.cmd_params.subopcode =
                                                 RIVA_POKE_OPCODE;
-             ret = hci_poke_data(&radio->riva_data_req);
+             ret = hci_poke_data(&hal->radio->riva_data_req);
          } else {
              ALOGE("%s: riva access len is not valid for poke\n", LOG_TAG);
              ret = -1;
@@ -1424,22 +1450,22 @@
          }
          break;
     case HCI_FM_HELIUM_SSBI_ACCS_ADDR:
-        radio->ssbi_data_accs.start_addr = val;
+        hal->radio->ssbi_data_accs.start_addr = val;
         break;
     case HCI_FM_HELIUM_SSBI_POKE:
-        radio->ssbi_data_accs.data = val;
-        ret = hci_ssbi_poke_reg(&radio->ssbi_data_accs);
+        hal->radio->ssbi_data_accs.data = val;
+        ret = hci_ssbi_poke_reg(&hal->radio->ssbi_data_accs);
         break;
     case HCI_FM_HELIUM_SSBI_PEEK:
-        radio->ssbi_peek_reg.start_address = val;
-        hci_ssbi_peek_reg(&radio->ssbi_peek_reg);
+        hal->radio->ssbi_peek_reg.start_address = val;
+        hci_ssbi_peek_reg(&hal->radio->ssbi_peek_reg);
         break;
     case HCI_FM_HELIUM_AGC_UCCTRL:
-        radio->set_get_reset_agc.ucctrl = val;
+        hal->radio->set_get_reset_agc.ucctrl = val;
         break;
     case HCI_FM_HELIUM_AGC_GAIN_STATE:
-        radio->set_get_reset_agc.ucgainstate = val;
-        hci_get_set_reset_agc_req(&radio->set_get_reset_agc);
+        hal->radio->set_get_reset_agc.ucgainstate = val;
+        hci_get_set_reset_agc_req(&hal->radio->set_get_reset_agc);
         break;
     case HCI_FM_HELIUM_SINR_SAMPLES:
          if (!is_valid_sinr_samples(val)) {
@@ -1447,8 +1473,8 @@
              ret = -1;
              goto end;
          }
-         radio->ch_det_threshold.sinr_samples = val;
-         ret = set_ch_det_thresholds_req(&radio->ch_det_threshold);
+         hal->radio->ch_det_threshold.sinr_samples = val;
+         ret = set_ch_det_thresholds_req(&hal->radio->ch_det_threshold);
          if (ret < 0) {
              ALOGE("Failed to set SINR samples  %d", ret);
              goto end;
@@ -1460,8 +1486,8 @@
              ret = -1;
              goto end;
          }
-         radio->ch_det_threshold.sinr = val;
-         ret = set_ch_det_thresholds_req(&radio->ch_det_threshold);
+         hal->radio->ch_det_threshold.sinr = val;
+         ret = set_ch_det_thresholds_req(&hal->radio->ch_det_threshold);
          break;
     case HCI_FM_HELIUM_INTF_LOW_THRESHOLD:
          if (!is_valid_intf_det_low_th(val)) {
@@ -1469,8 +1495,8 @@
              ret = -1;
              goto end;
          }
-         radio->ch_det_threshold.low_th = val;
-         ret = set_ch_det_thresholds_req(&radio->ch_det_threshold);
+         hal->radio->ch_det_threshold.low_th = val;
+         ret = set_ch_det_thresholds_req(&hal->radio->ch_det_threshold);
          break;
     case HCI_FM_HELIUM_INTF_HIGH_THRESHOLD:
          if (!is_valid_intf_det_hgh_th(val)) {
@@ -1478,30 +1504,30 @@
              ret = -1;
              goto end;
          }
-         radio->ch_det_threshold.high_th = val;
-         ret = set_ch_det_thresholds_req(&radio->ch_det_threshold);
+         hal->radio->ch_det_threshold.high_th = val;
+         ret = set_ch_det_thresholds_req(&hal->radio->ch_det_threshold);
          break;
     case HCI_FM_HELIUM_SINRFIRSTSTAGE:
          def_data_wrt.mode = FM_SRCH_CONFG_MODE;
          def_data_wrt.length = FM_SRCH_CNFG_LEN;
-         memcpy(&def_data_wrt.data, &radio->def_data.data,
-                 radio->def_data.data_len);
+         memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
+                 hal->radio->def_data.data_len);
          def_data_wrt.data[SINRFIRSTSTAGE_OFFSET] = val;
          ret = hci_fm_default_data_write_req(&def_data_wrt);
          break;
     case HCI_FM_HELIUM_RMSSIFIRSTSTAGE:
          def_data_wrt.mode = FM_SRCH_CONFG_MODE;
          def_data_wrt.length = FM_SRCH_CNFG_LEN;
-         memcpy(&def_data_wrt.data, &radio->def_data.data,
-                 radio->def_data.data_len);
+         memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
+                 hal->radio->def_data.data_len);
          def_data_wrt.data[RMSSIFIRSTSTAGE_OFFSET] = val;
          ret = hci_fm_default_data_write_req(&def_data_wrt);
          break;
     case HCI_FM_HELIUM_CF0TH12:
          def_data_wrt.mode = FM_SRCH_CONFG_MODE;
          def_data_wrt.length = FM_SRCH_CNFG_LEN;
-         memcpy(&def_data_wrt.data, &radio->def_data.data,
-                 radio->def_data.data_len);
+         memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
+                 hal->radio->def_data.data_len);
          def_data_wrt.data[CF0TH12_BYTE1_OFFSET] = (val & 0xFF);
          def_data_wrt.data[CF0TH12_BYTE2_OFFSET] = ((val >> 8) & 0xFF);
          ret = hci_fm_default_data_write_req(&def_data_wrt);
@@ -1509,40 +1535,40 @@
     case HCI_FM_HELIUM_SRCHALGOTYPE:
          def_data_wrt.mode = FM_SRCH_CONFG_MODE;
          def_data_wrt.length = FM_SRCH_CNFG_LEN;
-         memcpy(&def_data_wrt.data, &radio->def_data.data,
-                 radio->def_data.data_len);
+         memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
+                 hal->radio->def_data.data_len);
          def_data_wrt.data[SRCH_ALGO_TYPE_OFFSET] = val;
          ret = hci_fm_default_data_write_req(&def_data_wrt);
          break;
     case HCI_FM_HELIUM_AF_RMSSI_TH:
          def_data_wrt.mode = FM_AFJUMP_CONFG_MODE;
          def_data_wrt.length = FM_AFJUMP_CNFG_LEN;
-         memcpy(&def_data_wrt.data, &radio->def_data.data,
-                 radio->def_data.data_len);
+         memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
+                 hal->radio->def_data.data_len);
          def_data_wrt.data[AF_RMSSI_TH_OFFSET] = (val & 0xFF);
          ret = hci_fm_default_data_write_req(&def_data_wrt);
          break;
     case HCI_FM_HELIUM_GOOD_CH_RMSSI_TH:
          def_data_wrt.mode = FM_AFJUMP_CONFG_MODE;
          def_data_wrt.length = FM_AFJUMP_CNFG_LEN;
-         memcpy(&def_data_wrt.data, &radio->def_data.data,
-                 radio->def_data.data_len);
+         memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
+                 hal->radio->def_data.data_len);
          def_data_wrt.data[GD_CH_RMSSI_TH_OFFSET] = val;
          ret = hci_fm_default_data_write_req(&def_data_wrt);
          break;
     case HCI_FM_HELIUM_AF_RMSSI_SAMPLES:
          def_data_wrt.mode = FM_AFJUMP_CONFG_MODE;
          def_data_wrt.length = FM_AFJUMP_CNFG_LEN;
-         memcpy(&def_data_wrt.data, &radio->def_data.data,
-                 radio->def_data.data_len);
+         memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
+                 hal->radio->def_data.data_len);
          def_data_wrt.data[AF_RMSSI_SAMPLES_OFFSET] = val;
          ret = hci_fm_default_data_write_req(&def_data_wrt);
          break;
     case HCI_FM_HELIUM_RXREPEATCOUNT:
          def_data_wrt.mode = RDS_PS0_XFR_MODE;
          def_data_wrt.length = RDS_PS0_LEN;
-         memcpy(&def_data_wrt.data, &radio->def_data.data,
-                 radio->def_data.data_len);
+         memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
+                 hal->radio->def_data.data_len);
          def_data_wrt.data[AF_RMSSI_SAMPLES_OFFSET] = val;
          ret = hci_fm_default_data_write_req(&def_data_wrt);
          break;
@@ -1552,8 +1578,8 @@
              ret = -1;
              goto end;
          }
-         radio->blend_tbl.BlendSinrHi = val;
-         ret = hci_fm_set_blend_tbl_req(&radio->blend_tbl);
+         hal->radio->blend_tbl.BlendSinrHi = val;
+         ret = hci_fm_set_blend_tbl_req(&hal->radio->blend_tbl);
          break;
     case HCI_FM_HELIUM_BLEND_RMSSIHI:
          if (!is_valid_blend_value(val)) {
@@ -1561,8 +1587,8 @@
              ret = -1;
              goto end;
          }
-         radio->blend_tbl.BlendRmssiHi = val;
-         ret = hci_fm_set_blend_tbl_req(&radio->blend_tbl);
+         hal->radio->blend_tbl.BlendRmssiHi = val;
+         ret = hci_fm_set_blend_tbl_req(&hal->radio->blend_tbl);
          break;
     case HCI_FM_HELIUM_ENABLE_LPF:
          ALOGI("%s: val: %x", __func__, val);
@@ -1586,16 +1612,21 @@
     int ret = 0;
     struct hci_fm_def_data_rd_req def_data_rd;
 
+    if (!hal) {
+        ALOGE("%s:ALERT: command sent before hal_init", __func__);
+        return -FM_HC_STATUS_FAIL;
+    }
+
     ALOGE("%s: cmd = 0x%x", __func__, cmd);
     switch(cmd) {
     case HCI_FM_HELIUM_FREQ:
-        val = radio->fm_st_rsp.station_rsp.station_freq;
+        val = hal->radio->fm_st_rsp.station_rsp.station_freq;
         break;
     case HCI_FM_HELIUM_UPPER_BAND:
-        val = radio->recv_conf.band_high_limit;
+        val = hal->radio->recv_conf.band_high_limit;
         break;
     case HCI_FM_HELIUM_LOWER_BAND:
-        val = radio->recv_conf.band_low_limit;
+        val = hal->radio->recv_conf.band_low_limit;
         break;
     case HCI_FM_HELIUM_SINR_SAMPLES:
         set_bit(ch_det_th_mask_flag, CMD_CHDET_SINR_SAMPLE);
@@ -1699,7 +1730,7 @@
             clear_bit(station_dbg_param_mask_flag, CMD_STNDBGPARAM_INFDETOUT);
         break;
     case HCI_FM_HELIUM_GET_SINR:
-        if (radio->mode == FM_RECV) {
+        if (hal->radio->mode == FM_RECV) {
             set_bit(station_param_mask_flag, CMD_STNPARAM_SINR);
             ret = hci_fm_get_station_cmd_param_req();
             if (ret != FM_HC_STATUS_SUCCESS)
@@ -1710,12 +1741,12 @@
         }
         break;
     case HCI_FM_HELIUM_RMSSI:
-        if (radio->mode == FM_RECV) {
+        if (hal->radio->mode == FM_RECV) {
             set_bit(station_param_mask_flag, CMD_STNPARAM_RSSI);
             ret = hci_fm_get_station_cmd_param_req();
             if (ret != FM_HC_STATUS_SUCCESS)
                 clear_bit(station_param_mask_flag, CMD_STNPARAM_RSSI);
-        } else if (radio->mode == FM_TRANS) {
+        } else if (hal->radio->mode == FM_TRANS) {
             ALOGE("HCI_FM_HELIUM_RMSSI: radio is not in recv mode");
             ret = -EINVAL;
         }
@@ -1728,7 +1759,7 @@
     return ret;
 }
 
-const fm_interface_t FM_HELIUM_LIB_INTERFACE = {
+const struct fm_interface_t FM_HELIUM_LIB_INTERFACE = {
     hal_init,
     set_fm_ctrl,
     get_fm_ctrl
diff --git a/helium/radio_helium_hal_cmds.c b/helium/radio_helium_hal_cmds.c
index 7945023..520ec12 100644
--- a/helium/radio_helium_hal_cmds.c
+++ b/helium/radio_helium_hal_cmds.c
@@ -34,9 +34,10 @@
 #include <errno.h>
 #include "radio-helium-commands.h"
 #include "radio-helium.h"
-#include "fm_hci.h"
+#include "fm_hci_api.h"
 #include <dlfcn.h>
 #define LOG_TAG "radio_helium"
+extern struct fm_hal_t *hal;
 
 static int send_fm_cmd_pkt(uint16_t opcode,  uint32_t len, void *param)
 {
@@ -44,7 +45,7 @@
     int ret = 0;
     ALOGV("Send_fm_cmd_pkt, opcode: %x", opcode);
 //    pthread_mutex_lock(&fm_hal);
-    FM_HDR *hdr = (FM_HDR *) malloc(p_len);
+    struct fm_command_header_t *hdr = (struct fm_command_header_t *) malloc(p_len);
     if (!hdr) {
         ALOGE("%s:hdr allocation failed", LOG_TAG);
         return -FM_HC_STATUS_NOMEM;
@@ -52,12 +53,13 @@
 
     ALOGV("%s:opcode: %x", LOG_TAG, opcode);
 
-    hdr->protocol_byte = RADIO_HCI_COMMAND_PKT;
+    hdr->pi = RADIO_HCI_COMMAND_PKT;
     hdr->opcode = opcode;
-    hdr->plen = len;
+    hdr->len = len;
     if (len)
-        memcpy(hdr->cmd_params, (uint8_t *)param, len);
-    ret = transmit(hdr);
+        memcpy(hdr->params, (uint8_t *)param, len);
+    ret = fm_hci_transmit(hal->private_data, hdr);
+
     ALOGV("%s:transmit done. status = %d", __func__, ret);
     return ret;
 }
diff --git a/jni/android_hardware_fm.cpp b/jni/android_hardware_fm.cpp
index 163ce9b..d4d4e15 100644
--- a/jni/android_hardware_fm.cpp
+++ b/jni/android_hardware_fm.cpp
@@ -512,7 +512,6 @@
 
 typedef struct {
     int (*hal_init)(fm_vendor_callbacks_t *p_cb);
-
     int (*set_fm_ctrl)(int ioctl, int val);
     int (*get_fm_ctrl) (int ioctl, int val);
 } fm_interface_t;
@@ -704,7 +703,7 @@
     int err;
     ALOGE("id(%x) value: %x\n", id, value);
 #ifdef FM_SOC_TYPE_CHEROKEE
-	err = vendor_interface->set_fm_ctrl(id, value);
+    err = vendor_interface->set_fm_ctrl(id, value);
 #else
     if ((fd >= 0) && (id >= 0)) {
         err = FmIoctlsInterface :: set_control(fd, id, value);
@@ -928,7 +927,7 @@
     } else {
         err = freq;
     }
-	return err;
+    return err;
 #endif
     if (fd >= 0) {
         err = FmIoctlsInterface :: get_lowerband_limit(fd, freq);
@@ -962,7 +961,7 @@
     } else {
         err = freq;
     }
-	return err;
+    return err;
 #endif
     if (fd >= 0) {
         err = FmIoctlsInterface :: get_upperband_limit(fd, freq);
@@ -993,7 +992,7 @@
     } else {
         err = FM_JNI_SUCCESS;
     }
-	return err;
+    return err;
 #endif
     if (fd >= 0) {
         err = FmIoctlsInterface :: set_audio_mode(fd, (enum AUDIO_MODE)val);