diff --git a/fm_hci/Android.mk b/fm_hci/Android.mk
new file mode 100644
index 0000000000000000000000000000000000000000..1c4b9495980a8b58c422f04418f7edbe51cd3cfc
--- /dev/null
+++ b/fm_hci/Android.mk
@@ -0,0 +1,37 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Setup bdroid local make variables for handling configuration
+ifneq ($(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR),)
+  bdroid_C_INCLUDES := $(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR)
+  bdroid_CFLAGS += -DHAS_BDROID_BUILDCFG
+else
+  bdroid_C_INCLUDES :=
+  bdroid_CFLAGS += -DHAS_NO_BDROID_BUILDCFG
+endif
+
+BDROID_DIR:= external/bluetooth/bluedroid
+
+LOCAL_CFLAGS += $(bdroid_CFLAGS)
+
+LOCAL_SRC_FILES := \
+	fm_hci.c
+
+LOCAL_SHARED_LIBRARIES := \
+         libdl \
+         libcutils
+
+LOCAL_CFLAGS := -Wno-unused-parameter
+
+LOCAL_CFLAGS += -std=c99
+
+LOCAL_C_INCLUDES += \
+        $(BDROID_DIR)/hci/include \
+        $(LOCAL_PATH)/../helium
+
+LOCAL_MODULE := libfm-hci
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/fm_hci/fm_hci.c b/fm_hci/fm_hci.c
new file mode 100644
index 0000000000000000000000000000000000000000..2c3e2dfd5f9f9e86f1700d5170b5441bbcf742b5
--- /dev/null
+++ b/fm_hci/fm_hci.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#define LOG_TAG "fm_hci_helium"
+
+#include <assert.h>
+#include <utils/Log.h>
+
+#include "bt_hci_bdroid.h"
+#include "bt_vendor_lib.h"
+#include "hci.h"
+#include "userial.h"
+#include "utils.h"
+#include "fm_hci.h"
+#include "wcnss_hci.h"
+#include <dlfcn.h>
+#include <sys/eventfd.h>
+#include <errno.h>
+
+int fd;
+fm_hal_cb *hal_cb;
+
+void event_notification(uint16_t event)
+{
+    pthread_mutex_lock(&fmHCIControlBlock.event_lock);
+    ready_events |= event;
+    pthread_cond_signal(&fmHCIControlBlock.event_cond);
+    ALOGI("%s: Notifying worker thread with event: %d", __func__, event);
+    pthread_mutex_unlock(&fmHCIControlBlock.event_lock);
+}
+
+bt_vendor_interface_t *fm_vnd_if = NULL;
+void init_vnd_if()
+{
+    void *dlhandle;
+    unsigned char bdaddr[] = {0xaa, 0xbb, 0xcc, 0x11, 0x22, 0x33};
+
+    dlhandle = dlopen("libbt-vendor.so", RTLD_NOW);
+    if (!dlhandle)
+    {
+        ALOGE("!!! Failed to load libbt-vendor.so !!!");
+        return;
+    }
+
+    fm_vnd_if = (bt_vendor_interface_t *) dlsym(dlhandle, "BLUETOOTH_VENDOR_LIB_INTERFACE");
+    if (!fm_vnd_if)
+    {
+        ALOGE("!!! Failed to get bt vendor interface !!!");
+        return;
+    }
+
+    ALOGI("FM-HCI: Registering the WCNSS HAL library by passing CBs and BD addr.");
+    fm_vnd_if->init(&fm_vendor_callbacks, bdaddr);
+}
+
+volatile uint16_t command_credits;
+
+/* De-queues the FM CMD from the TX_Q */
+void dequeue_fm_tx_cmd()
+{
+	TX_Q *new_first, *new_last;
+	static int cmd_count = 0;
+	static uint8_t credits = 0;
+	uint8_t i;
+	uint8_t temp_1 = 0x11;
+
+	if (cmd_count >= MAX_FM_CMD_CNT) {
+		ALOGI("\n\n\t\tReached Max. CMD COUNT!!\n\n");
+		lib_running = 0;
+		return;
+	}
+
+	/*
+	 * 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);
+
+	//credits = command_credits;
+
+	TX_Q *temp = new_first;
+	while(temp != NULL) {
+
+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_unlock(&fmHCIControlBlock.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 (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));
+			/* Use socket 'fd' to send the command down to WCNSS Filter */
+			write(fd, (uint8_t *)temp->hdr, (sizeof(FM_HDR) + temp->hdr->plen));
+			//write(fd, &temp_1, 1);
+
+			/* 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;
+		} 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 int read_fm_event(int fd, FM_EVT_HDR *pbuf, int len)
+{
+    fd_set readFds;
+    int n = 0, ret = -1, evt_type = -1, evt_len = -1;
+
+    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);
+
+        ALOGE("%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);
+        if (n > 0)
+        {
+            /* Check if event is available or not */
+#if 1
+            if (FD_ISSET(fd, &readFds)) {
+                ret = read(fd, (uint8_t *)pbuf, (size_t)(sizeof(FM_EVT_HDR) + MAX_FM_EVT_PARAMS));
+                if (0 == ret) {
+                    ALOGE("%s: read() returned '0' bytes\n", __func__);
+                }
+                else {
+                    ALOGE("%s: read() returned %d bytes of FM event/data\n", __func__, ret);
+                    while (ret > 0) {
+                        if (pbuf->evt_code == FM_CMD_COMPLETE) {
+                            ALOGE("\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;
+                        } else if (pbuf->evt_code == FM_CMD_STATUS) {
+                            ALOGE("\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;
+                        } else {
+                            ALOGI("%s: Not CS/CC Event: Recvd. Event Code: 0x%2x", __func__, pbuf->evt_code);
+                            evt_type = -1;
+                        }
+
+                        evt_len = pbuf->evt_len;
+
+                        /* Notify 'fmHCITask' about availability of event or data */
+                        ALOGE("%s: \nNotifying 'fmHCITask' availability of FM event or data...\n", __func__);
+                        event_notification(HC_EVENT_RX);
+
+                        if (hal_cb && hal_cb->fm_evt_notify != NULL)
+                            hal_cb->fm_evt_notify((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) {
+                                ALOGE("\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) {
+                                ALOGE("\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);
+                        ALOGE("%s: Length of available bytes @ HCI Layer: %d", __func__, ret);
+
+                        if (ret > 0) {
+                            ALOGE("%s: Remaining bytes of event/data: %d", __func__, ret);
+                            pbuf = (FM_EVT_HDR *)&pbuf->cmd_params[evt_len];
+                            ALOGE("%s: Protocol byte of next packet: 0x%2x", __func__, pbuf[0]);
+                        }
+
+                    }
+                } //end of processing the event
+
+            } else
+                ALOGE("%s: No data available, though select returned!!!\n", __func__);
+#endif
+        }
+        else if (n < 0)
+            ALOGE("%s: select() failed with return value: %d", __func__, ret);
+        else if (n == 0)
+            ALOGE("%s: select() timeout!!!", __func__);
+    }
+
+    return ret;
+}
+
+static void *userial_read_thread(void *arg)
+{
+	int length;
+
+	while(lib_running) {
+
+                FM_EVT_HDR *evt_buf = (FM_EVT_HDR *) malloc(sizeof(FM_EVT_HDR) + MAX_FM_EVT_PARAMS);
+
+		ALOGE("%s: Wait for events from the WCNSS Filter", __func__);
+		length = read_fm_event(fd, evt_buf, sizeof(FM_EVT_HDR) + MAX_FM_EVT_PARAMS);
+
+#if 0
+		if (length > 0) {
+			//TODO: Copy the data to the RX-Q
+			//TODO: Notify event/data availability
+			ALOGE("%s: FM Event or RDS data available: Notify FM-HAL Layer", __func__);
+			event_notification(HC_EVENT_RX);
+		} else
+			ALOGE("%s: return value from read_fm_event(): %d", __func__, length);
+#endif
+		//TODO: Have condition for breaking from the loop!
+	}
+	lib_running = 0;
+	ALOGE("%s: Leaving userial_read_thread()", __func__);
+	pthread_exit(NULL);
+
+	return arg;
+}
+
+/*
+ * Reads the FM-CMDs from the TX_Q 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 uint16_t events;
+
+	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);
+
+		if ((events & 0xFFF8) == HC_EVENT_TX) {
+			ALOGI("\n@@@@@ FM-HCI Task : EVENT_TX available @@@@@\n");
+			dequeue_fm_tx_cmd();
+		}
+		if ((events & 0xFFF4) == HC_EVENT_RX) {
+			ALOGI("\n##### FM-HCI Task : EVENT_RX available #####\n");
+			//TODO: Notify FM-HAL about event/data availablity
+		}
+	}
+        ALOGE("%s: ##### Exiting fmHCITask Worker thread!!! #####", __func__);
+	return arg;
+}
+
+int fm_hci_init(fm_hal_cb *p_cb)
+{
+    pthread_attr_t thread_attr;
+    struct sched_param param;
+    int policy, result, hci_type;
+
+    ALOGI("FM-HCI: init");
+
+    /* Save the FM-HAL event notofication callback func. */
+    hal_cb = p_cb;
+
+    ALOGI("FM-HCI: Loading the WCNSS HAL library...");
+    init_vnd_if();
+
+    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);
+
+    ALOGI("FM-HCI: Creating the FM-HCI TASK...");
+    if (pthread_create(&fmHCIControlBlock.fmHCITaskThreadId, &thread_attr, \
+                       fmHCITask, NULL) != 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)
+    {
+        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);
+        if (result != 0)
+        {
+            ALOGW("libbt-hci init: pthread_setschedparam failed (%s)", \
+                  strerror(result));
+        }
+    } else
+        ALOGI("FM-HCI: Failed to get the Scheduling parameters!!!");
+
+    return FM_HC_STATUS_SUCCESS;
+}
+
+
+void fm_power(fm_power_state state)
+{
+    int val;
+
+    if (state) {
+        ALOGI("FM-HCI: %s: Turning FM ON", __func__);
+        val = state;
+        fm_vnd_if->op(FM_VND_OP_POWER_CTRL, &val);
+    } else {
+        ALOGI("FM-HCI: %s: Turning FM OFF", __func__);
+        val = state;
+        fm_vnd_if->op(FM_VND_OP_POWER_CTRL, &val);
+    }
+}
+
+#define CH_MAX 3
+int open_serial_port()
+{
+    int i, ret;
+    int fd_array[CH_MAX];
+
+    for (int i = 0; i < CH_MAX; i++)
+        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);
+
+    fd = fd_array[0];
+    if (fd == -1) {
+        ALOGE("%s unable to open TTY serial port", __func__);
+        goto err;
+    }
+
+    //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;
+
+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;
+}
+
+void enqueue_fm_tx_cmd(FM_HDR *pbuf)
+{
+
+	pthread_mutex_lock(&fmHCIControlBlock.tx_q_lock);
+
+	if (!fmHCIControlBlock.first) {
+		fmHCIControlBlock.first = (TX_Q *) malloc(sizeof(TX_Q));
+		if (!fmHCIControlBlock.first) {
+			printf("Failed to allocate memory for first!!\n");
+			pthread_mutex_unlock(&fmHCIControlBlock.tx_q_lock);
+			return;
+		}
+		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) {
+			printf("Failed to allocate memory for element!!\n");
+			pthread_mutex_unlock(&fmHCIControlBlock.tx_q_lock);
+			return;
+		}
+		fmHCIControlBlock.last->next = element;
+		element->hdr = pbuf;
+		element->next = NULL;
+		fmHCIControlBlock.last = element;
+                ALOGI("%s: fm-cmd enqueued successfully", __func__);
+	}
+
+	pthread_mutex_unlock(&fmHCIControlBlock.tx_q_lock);
+}
+
+/** Transmit frame */
+void transmit(FM_HDR *pbuf)
+{
+    enqueue_fm_tx_cmd(pbuf);
+    event_notification(HC_EVENT_TX);
+}
diff --git a/fm_hci/fm_hci.h b/fm_hci/fm_hci.h
new file mode 100644
index 0000000000000000000000000000000000000000..585411eae4e4c24edcaf0f07261e04cb3cfd5fcb
--- /dev/null
+++ b/fm_hci/fm_hci.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2015, 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__
+#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;
+
+/* Host/Controller lib internal event ID */
+#define HC_EVENT_PRELOAD               0x0001
+#define HC_EVENT_POSTLOAD              0x0002
+#define HC_EVENT_RX                    0x0004
+#define HC_EVENT_TX                    0x0008
+#define HC_EVENT_LPM_ENABLE            0x0010
+#define HC_EVENT_LPM_DISABLE           0x0020
+#define HC_EVENT_LPM_WAKE_DEVICE       0x0040
+#define HC_EVENT_LPM_ALLOW_SLEEP       0x0080
+#define HC_EVENT_LPM_IDLE_TIMEOUT      0x0100
+#define HC_EVENT_EXIT                  0x0200
+#define HC_EVENT_EPILOG                0x0400
+
+#define MAX_FM_CMD_CNT                 100
+#define FM_CMD                         0x11
+#define FM_EVT                         0x14
+#define MAX_FM_EVT_PARAMS              255
+
+#define FM_CMD_COMPLETE 0x0f
+#define FM_CMD_STATUS   0x10
+
+static pthread_mutex_t utils_mutex;
+
+static volatile uint8_t lib_running = 0;
+static volatile uint16_t ready_events = 0;
+
+FILE *fd_wcnss_filter;
+
+typedef struct {
+    uint8_t protocol_byte;
+    uint16_t opcode;
+    uint8_t plen;
+    uint8_t cmd_params[];
+} FM_HDR;
+
+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;
+
+void transmit(FM_HDR *pbuf);
+int  fm_hci_init(fm_hal_cb *);
+void fm_power(fm_power_state state);
+int open_serial_port(void);
+
+typedef struct {
+    pthread_mutex_t tx_q_lock;
+    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;
+
+    TX_Q *first;
+    TX_Q *last;
+
+} fmHCIControlStructure;
+
+fmHCIControlStructure fmHCIControlBlock;
+
+#endif
diff --git a/fm_hci/wcnss_hci.h b/fm_hci/wcnss_hci.h
new file mode 100644
index 0000000000000000000000000000000000000000..95fa9c125bf9d31d125c8f613f63abcb3cda825d
--- /dev/null
+++ b/fm_hci/wcnss_hci.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, 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 __WCNSS_HCI__
+#define __WCNSS_HCI__
+static void vendor_fwcfg_cb(bt_vendor_op_result_t result) {
+}
+
+static void vendor_scocfg_cb(bt_vendor_op_result_t result) {
+}
+
+static void vendor_lpm_vnd_cb(bt_vendor_op_result_t result) {
+}
+
+static void sco_audiostate_cb(bt_vendor_op_result_t result) {
+}
+
+static void* vendor_alloc(int size) {
+    return NULL;
+}
+
+static void vendor_dealloc(void *p_buf) {
+}
+
+static uint8_t vendor_xmit_cb(uint16_t opcode, void *p_buf, tINT_CMD_CBACK p_cback) {
+    return 0;
+}
+
+static void vendor_epilog_cb(bt_vendor_op_result_t result) {
+}
+
+
+static const bt_vendor_callbacks_t fm_vendor_callbacks = {
+  sizeof(fm_vendor_callbacks),
+   vendor_fwcfg_cb,
+   vendor_scocfg_cb,
+   vendor_lpm_vnd_cb,
+   sco_audiostate_cb,
+   vendor_alloc,
+   vendor_dealloc,
+   vendor_xmit_cb,
+   vendor_epilog_cb
+};
+#endif