diff --git a/fm_hci/fm_hci.c b/fm_hci/fm_hci.c index fec8bc7bc19299a8dafb7aa0f47535b877dd641a..1394565597f12a0f3ca667584c71526c983b50d8 100644 --- a/fm_hci/fm_hci.c +++ b/fm_hci/fm_hci.c @@ -43,7 +43,7 @@ #include <sys/eventfd.h> #include <errno.h> -int fd; +int fm_fd; fm_hal_cb *hal_cb; void event_notification(uint16_t event) @@ -146,7 +146,7 @@ wait_for_cmd_credits: ALOGE("%s: Sizeof FM_HDR: %d", __func__, (int)sizeof(temp->hdr)); /* Use socket 'fd' to send the command down to WCNSS Filter */ - write(fd, (uint8_t *)temp->hdr, (sizeof(FM_HDR) + temp->hdr->plen)); + write(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*/ @@ -193,6 +193,10 @@ static inline uint64_t read_event() { 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) { @@ -242,6 +246,12 @@ static int read_fm_event(int fd, FM_EVT_HDR *pbuf, int len) __func__, ret, pbuf->protocol_byte, pbuf->evt_code, pbuf->evt_len, pbuf->cmd_params[3], pbuf->cmd_params[2], pbuf->cmd_params[1], pbuf->cmd_params[0]); evt_type = FM_CMD_STATUS; + } else 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; + // 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; @@ -290,8 +300,10 @@ static int read_fm_event(int fd, FM_EVT_HDR *pbuf, int len) ALOGE("%s: No data available, though select returned!!!\n", __func__); #endif } - else if (n < 0) - ALOGE("%s: select() failed with return value: %d", __func__, ret); + else if (n < 0) { + ALOGE("%s: select() failed with return value: %d", __func__, ret); + lib_running =0; + } else if (n == 0) ALOGE("%s: select() timeout!!!", __func__); } @@ -303,29 +315,17 @@ static void *userial_read_thread(void *arg) { int length; - while(lib_running) { - - FM_EVT_HDR *evt_buf = (FM_EVT_HDR *) malloc(sizeof(FM_EVT_HDR) + MAX_FM_EVT_PARAMS); - - ALOGE("%s: Wait for events from the WCNSS Filter", __func__); - length = read_fm_event(fd, evt_buf, sizeof(FM_EVT_HDR) + MAX_FM_EVT_PARAMS); - -#if 0 - if (length > 0) { - //TODO: Copy the data to the RX-Q - //TODO: Notify event/data availability - ALOGE("%s: FM Event or RDS data available: Notify FM-HAL Layer", __func__); - event_notification(HC_EVENT_RX); - } else - ALOGE("%s: return value from read_fm_event(): %d", __func__, length); -#endif - //TODO: Have condition for breaking from the loop! - } - lib_running = 0; - ALOGE("%s: Leaving userial_read_thread()", __func__); - pthread_exit(NULL); - - return arg; + 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; } /* @@ -443,8 +443,8 @@ int open_serial_port() ALOGI("%s: Opening the TTy Serial port...", __func__); ret = fm_vnd_if->op(BT_VND_OP_FM_USERIAL_OPEN, &fd_array); - fd = fd_array[0]; - if (fd == -1) { + fm_fd = fd_array[0]; + if (fm_fd == -1) { ALOGE("%s unable to open TTY serial port", __func__); goto err; } @@ -506,3 +506,27 @@ void transmit(FM_HDR *pbuf) enqueue_fm_tx_cmd(pbuf); event_notification(HC_EVENT_TX); } + +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); + if (result) + ALOGE("%s failed to join reader thread: %d", __func__, result); + return; + } + ALOGW("%s Already closed userial reader thread", __func__); +} + +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; +} diff --git a/fm_hci/fm_hci.h b/fm_hci/fm_hci.h index 585411eae4e4c24edcaf0f07261e04cb3cfd5fcb..431179b0db3644a2b424b459f2130b86ea5769c2 100644 --- a/fm_hci/fm_hci.h +++ b/fm_hci/fm_hci.h @@ -69,6 +69,7 @@ typedef enum { #define FM_CMD_COMPLETE 0x0f #define FM_CMD_STATUS 0x10 +#define FM_HW_ERR_EVENT 0x1A static pthread_mutex_t utils_mutex; diff --git a/helium/radio-helium.h b/helium/radio-helium.h index 9952884024e40e3e2279e4aa97d81826f660e209..8599316b494cb95e20f5bf12e007a383535784c8 100644 --- a/helium/radio-helium.h +++ b/helium/radio-helium.h @@ -497,6 +497,8 @@ struct hci_fm_blend_table { #define HCI_EV_SEARCH_LIST_COMPLETE 0x14 #define HCI_EV_RADIO_TEXT_PLUS_ID 0x18 #define HCI_EV_RADIO_TEXT_PLUS_TAG 0x19 +#define HCI_EV_HW_ERR_EVENT 0x1A + #define HCI_REQ_DONE 0 #define HCI_REQ_PEND 1 diff --git a/helium/radio_helium_hal.c b/helium/radio_helium_hal.c index 0c68972b0215d0357efae9c25ea860061c0d1a95..a9aa9f06cd82a44309ad64d8399bdb29a9b26f4a 100644 --- a/helium/radio_helium_hal.c +++ b/helium/radio_helium_hal.c @@ -103,6 +103,9 @@ static void hci_cc_fm_disable_rsp(char *ev_buff) if (radio->mode == FM_TURNING_OFF) { jni_cb->disabled_cb(); radio->mode = FM_OFF; + //close the userial port and power off the chip + fm_userial_close(); + fm_power(FM_RADIO_DISABLE); } } @@ -514,6 +517,13 @@ static void hci_ev_ert() } } +static void hci_ev_hw_error(char *buff) +{ + ALOGE("%s:%s: start", LOG_TAG, __func__); + jni_cb->disabled_cb(); + fm_userial_close(); +} + static void hci_buff_ert(struct rds_grp_data *rds_buf) { int i; @@ -701,6 +711,9 @@ void radio_hci_event_packet(char *evt_buf) case HCI_EV_RADIO_TEXT_PLUS_TAG: hci_ev_rt_plus_tag(((FM_EVT_HDR *)evt_buf)->cmd_params); break; + case HCI_EV_HW_ERR_EVENT: + hci_ev_hw_error(((FM_EVT_HDR *)evt_buf)->cmd_params); + break; default: break; } diff --git a/qcom/fmradio/FmReceiverJNI.java b/qcom/fmradio/FmReceiverJNI.java index 8a2be0fe2ead64f640d6f82dcc8a5dc6f3b0c35d..d8743e88e521fb9ca637a49ce116b93bc7e3d740 100644 --- a/qcom/fmradio/FmReceiverJNI.java +++ b/qcom/fmradio/FmReceiverJNI.java @@ -202,10 +202,18 @@ class FmReceiverJNI { public void disableCallback() { Log.e(TAG, "disableCallback enter"); - FmTransceiver.setFMPowerState(FmTransceiver.FMState_Turned_Off); - Log.v(TAG, "RxEvtList: CURRENT-STATE : FMTurningOff ---> NEW-STATE : FMOff"); - FmReceiver.mCallback.FmRxEvDisableReceiver(); - Log.e(TAG, "disableCallback exit"); + if (FmTransceiver.getFMPowerState() == FmTransceiver.subPwrLevel_FMTurning_Off) { + /*Set the state as FMOff */ + FmTransceiver.setFMPowerState(FmTransceiver.FMState_Turned_Off); + Log.v(TAG, "RxEvtList: CURRENT-STATE : FMTurningOff ---> NEW-STATE : FMOff"); + FmReceiver.mCallback.FmRxEvDisableReceiver(); + } else { + FmTransceiver.setFMPowerState(FmTransceiver.FMState_Turned_Off); + Log.d(TAG, "Unexpected RADIO_DISABLED recvd"); + Log.v(TAG, "RxEvtList: CURRENT-STATE : FMRxOn ---> NEW-STATE : FMOff"); + FmReceiver.mCallback.FmRxEvRadioReset(); + Log.e(TAG, "disableCallback exit"); + } } public FmReceiverJNI(FmRxEvCallbacks callback) {