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, ¶m)==0)
+ if(pthread_getschedparam(hci->tx_thread, &policy, ¶m)==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, ¶m);
+ result = pthread_setschedparam(hci->tx_thread, policy, ¶m);
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);