FM : Add new hci commands and compile changes
Added HAL changes for hci commands like peek, poke, get/set of
SINR sample/threshold.Compile time changes for adding correct
includes based on new bluetooth stack structure, code cleanup
and indendation.
Change-Id: I5e48f0c0dc6165d61335c6d8cc269891e26dd548
diff --git a/fm_hci/Android.mk b/fm_hci/Android.mk
index 1c4b949..2546902 100644
--- a/fm_hci/Android.mk
+++ b/fm_hci/Android.mk
@@ -11,7 +11,7 @@
bdroid_CFLAGS += -DHAS_NO_BDROID_BUILDCFG
endif
-BDROID_DIR:= external/bluetooth/bluedroid
+BDROID_DIR:= system/bt
LOCAL_CFLAGS += $(bdroid_CFLAGS)
@@ -28,6 +28,8 @@
LOCAL_C_INCLUDES += \
$(BDROID_DIR)/hci/include \
+ $(BDROID_DIR)/stack/include \
+ $(BDROID_DIR)/osi/include \
$(LOCAL_PATH)/../helium
LOCAL_MODULE := libfm-hci
diff --git a/fm_hci/fm_hci.c b/fm_hci/fm_hci.c
index 1394565..e0294ee 100644
--- a/fm_hci/fm_hci.c
+++ b/fm_hci/fm_hci.c
@@ -34,18 +34,24 @@
#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>
+#include <string.h>
int fm_fd;
fm_hal_cb *hal_cb;
+// 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
+};
+
void event_notification(uint16_t event)
{
pthread_mutex_lock(&fmHCIControlBlock.event_lock);
@@ -84,90 +90,90 @@
/* 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;
+ 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;
- }
+ 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);
+ /*
+ * 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;
+ //credits = command_credits;
- TX_Q *temp = new_first;
- while(temp != NULL) {
+ 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);
+ 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);
+ /* 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__);
+ 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(fm_fd, (uint8_t *)temp->hdr, (sizeof(FM_HDR) + temp->hdr->plen));
- //write(fd, &temp_1, 1);
+ ALOGE("%s: Sizeof FM_HDR: %d", __func__, (int)sizeof(temp->hdr));
+ /* 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);
- /* Decrement cmd credits by '1' after sending the cmd*/
- command_credits--;
+ /* 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--;
+ /* 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;
+ /* 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;
- }
- }
+ ALOGI("\n\n\t\tFalse wakeup: Yet to get COMMAND CREDITS from CONTROLLER\n\n");
+ goto wait_for_cmd_credits;
+ }
+ }
}
@@ -218,30 +224,29 @@
FD_SET(event_fd, &readFds);
int fd_max = (event_fd > fd ? event_fd : fd);
- ALOGE("%s: Waiting for events from WCNSS FILTER...\n", __func__);
+ 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);
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__);
+ ALOGD("%s: read() returned '0' bytes\n", __func__);
}
else {
- ALOGE("%s: read() returned %d bytes of FM event/data\n", __func__, ret);
+ ALOGV("%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"
+ ALOGV("\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"
+ ALOGV("\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]);
@@ -251,7 +256,6 @@
lib_running =0;
// commented till bt vendor include added
// fm_vnd_if->ssr_cleanup();
-
} else {
ALOGI("%s: Not CS/CC Event: Recvd. Event Code: 0x%2x", __func__, pbuf->evt_code);
evt_type = -1;
@@ -260,7 +264,7 @@
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__);
+ ALOGI("%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)
@@ -272,11 +276,11 @@
/* 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],
+ 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) {
- 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],
+ 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];
}
@@ -297,8 +301,7 @@
} //end of processing the event
} else
- ALOGE("%s: No data available, though select returned!!!\n", __func__);
-#endif
+ ALOGV("%s: No data available, though select returned!!!\n", __func__);
}
else if (n < 0) {
ALOGE("%s: select() failed with return value: %d", __func__, ret);
@@ -313,19 +316,19 @@
static void *userial_read_thread(void *arg)
{
- int length;
+ int length;
- FM_EVT_HDR *evt_buf = (FM_EVT_HDR *) malloc(sizeof(FM_EVT_HDR) + MAX_FM_EVT_PARAMS);
+ 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(fm_fd, evt_buf, sizeof(FM_EVT_HDR) + MAX_FM_EVT_PARAMS);
- ALOGE("length=%d\n",length);
- if(length <=0){
- lib_running =0;
- }
- ALOGE("%s: Leaving userial_read_thread()", __func__);
- pthread_exit(NULL);
- return arg;
+ ALOGE("%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);
+ ALOGE("length=%d\n",length);
+ if(length <=0) {
+ lib_running =0;
+ }
+ ALOGE("%s: Leaving userial_read_thread()", __func__);
+ pthread_exit(NULL);
+ return arg;
}
/*
@@ -334,29 +337,37 @@
*/
static void* fmHCITask(void *arg)
{
- static uint16_t events;
+ 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);
- while (lib_running) {
- pthread_mutex_lock(&fmHCIControlBlock.event_lock);
- while (ready_events == 0) {
- pthread_cond_wait(&fmHCIControlBlock.event_cond, &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");
+ }
+ }
- 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;
+ ALOGE("%s: ##### Exiting fmHCITask Worker thread!!! #####", __func__);
+ ret = pthread_mutex_unlock(&fmHCIControlBlock.credit_lock);
+ ALOGE("%s: credit lock ret value =%d #####", __func__, ret);
+ pthread_mutex_destroy(&fmHCIControlBlock.credit_lock);
+ ret = pthread_mutex_unlock(&fmHCIControlBlock.tx_q_lock);
+ ALOGE("%s: tx queue lock ret value =%d #####", __func__, ret);
+ pthread_mutex_destroy(&fmHCIControlBlock.tx_q_lock);
+ ret = pthread_mutex_unlock(&fmHCIControlBlock.event_lock);
+ ALOGE("%s: event lock ret value =%d #####", __func__, ret);
+ pthread_mutex_destroy(&fmHCIControlBlock.event_lock);
+ return arg;
}
int fm_hci_init(fm_hal_cb *p_cb)
@@ -470,34 +481,34 @@
void enqueue_fm_tx_cmd(FM_HDR *pbuf)
{
- pthread_mutex_lock(&fmHCIControlBlock.tx_q_lock);
+ 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;
+ 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;
+ } 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);
+ pthread_mutex_unlock(&fmHCIControlBlock.tx_q_lock);
}
/** Transmit frame */
@@ -510,8 +521,8 @@
void userial_close_reader(void) {
// Join the reader thread if it is still running.
if (lib_running) {
- // send_event(USERIAL_RX_EXIT);
- int result = pthread_join(&fmHCIControlBlock.fmRxTaskThreadId, NULL);
+ 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);
return;
@@ -520,13 +531,23 @@
}
void fm_userial_close(void) {
- if (lib_running) {
- int result = pthread_join(&fmHCIControlBlock.fmRxTaskThreadId, NULL);
- if (result)
- ALOGE("%s failed to join reader thread: %d", __func__, result);
- }
- fm_vnd_if->op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
- // Free all buffers still waiting in the RX queue.
- // TODO: use list data structure and clean this up.
- fm_fd = -1;
+
+ pthread_cond_signal(&fmHCIControlBlock.event_cond);
+ pthread_cond_destroy(&fmHCIControlBlock.event_cond);
+ pthread_cond_signal(&fmHCIControlBlock.cmd_credits_cond);
+ pthread_cond_destroy(&fmHCIControlBlock.cmd_credits_cond);
+
+ // Join the reader thread if it's 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);
+ }
+ lib_running =0;
+ ALOGE("%s close fm userial ", __func__);
+ fm_vnd_if->op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
+ // Free all buffers still waiting in the RX queue.
+ // TODO: use list data structure and clean this up.
+ fm_fd = -1;
}
diff --git a/fm_hci/fm_hci.h b/fm_hci/fm_hci.h
index 431179b..8ffbf04 100644
--- a/fm_hci/fm_hci.h
+++ b/fm_hci/fm_hci.h
@@ -102,6 +102,7 @@
int fm_hci_init(fm_hal_cb *);
void fm_power(fm_power_state state);
int open_serial_port(void);
+void fm_userial_close(void);
typedef struct {
pthread_mutex_t tx_q_lock;