summaryrefslogtreecommitdiffstats
path: root/helium/radio_helium_hal.c
diff options
context:
space:
mode:
authorSmriti Gupta <smritig@codeaurora.org>2017-06-23 12:59:21 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2017-12-07 11:42:37 -0800
commitdb534b0d8d4b27fa6e69cb16b69cc7e8ed70aff7 (patch)
tree3e63adccf2d34a875b917a614c66368fdf273616 /helium/radio_helium_hal.c
parentafc99d37f38b5ad88a354b81835a4d4737edc46a (diff)
downloadandroid_hardware_qcom_fm-db534b0d8d4b27fa6e69cb16b69cc7e8ed70aff7.tar.gz
android_hardware_qcom_fm-db534b0d8d4b27fa6e69cb16b69cc7e8ed70aff7.tar.bz2
android_hardware_qcom_fm-db534b0d8d4b27fa6e69cb16b69cc7e8ed70aff7.zip
FM : Fix wrong data being written to controller
In some commands, set/write data to controller, we assign one offset value in structure and send it to controller. We don't read data from controller before writing. It may cause writing wrong data to controller, as the structure may have some garbage values for other offsets. Errenous data written to controller, may cause functional failures. Change-Id: I102c0a256ab19de0d89db4f6da20df0c2522dff3 CRs-fixed: 2031064
Diffstat (limited to 'helium/radio_helium_hal.c')
-rw-r--r--helium/radio_helium_hal.c262
1 files changed, 249 insertions, 13 deletions
diff --git a/helium/radio_helium_hal.c b/helium/radio_helium_hal.c
index 2fd849a..f356f5f 100644
--- a/helium/radio_helium_hal.c
+++ b/helium/radio_helium_hal.c
@@ -118,6 +118,13 @@ static void hci_cc_fm_disable_rsp(char *ev_buff)
if (hal->radio->mode == FM_TURNING_OFF) {
ALOGD("%s:calling fm close\n", LOG_TAG );
fm_hci_close(hal->private_data);
+ free(hal->radio);
+ hal->radio = NULL;
+ hal->jni_cb = NULL;
+ pthread_cond_destroy(&hal->cmd_cond);
+ pthread_mutex_destroy(&hal->cmd_lock);
+ free(hal);
+ hal = NULL;
}
}
@@ -244,7 +251,14 @@ static void hci_cc_get_ch_det_threshold_rsp(char *ev_buff)
val = hal->radio->ch_det_threshold.high_th;
}
clear_all_bit(ch_det_th_mask_flag);
- hal->jni_cb->fm_get_ch_det_thr_cb(val, status);
+
+ if (!hal->set_cmd_sent)
+ hal->jni_cb->fm_get_ch_det_thr_cb(val, status);
+ else {
+ pthread_mutex_lock(&hal->cmd_lock);
+ pthread_cond_broadcast(&hal->cmd_cond);
+ pthread_mutex_unlock(&hal->cmd_lock);
+ }
}
static void hci_cc_set_ch_det_threshold_rsp(char *ev_buff)
@@ -327,7 +341,15 @@ static void hci_cc_default_data_read_rsp(char *ev_buff)
} else {
ALOGE("%s: Error: Status= 0x%x", __func__, status);
}
- hal->jni_cb->fm_def_data_read_cb(val, status);
+ if (!hal->set_cmd_sent)
+ hal->jni_cb->fm_def_data_read_cb(val, status);
+ else {
+ pthread_mutex_lock(&hal->cmd_lock);
+ pthread_cond_broadcast(&hal->cmd_cond);
+ pthread_mutex_unlock(&hal->cmd_lock);
+ }
+
+
}
static void hci_cc_default_data_write_rsp(char *ev_buff)
@@ -353,18 +375,28 @@ static void hci_cc_get_blend_tbl_rsp(char *ev_buff)
memcpy(&hal->radio->blend_tbl, &ev_buff[1],
sizeof(struct hci_fm_blend_table));
- ALOGE("hci_cc_get_blend_tbl_rsp: data");
+ ALOGD("hci_cc_get_blend_tbl_rsp: data");
int i;
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 = hal->radio->blend_tbl.BlendSinrHi;
+ ALOGE("%s: Sinrhi val = %d", LOG_TAG, val);
+ clear_bit(blend_tbl_mask_flag, CMD_BLENDTBL_SINR_HI);
} else if (test_bit(blend_tbl_mask_flag, CMD_BLENDTBL_RMSSI_HI)) {
val = hal->radio->blend_tbl.BlendRmssiHi;
+ ALOGE("%s: BlendRmssiHi val = %d", LOG_TAG, val);
+ clear_bit(blend_tbl_mask_flag, CMD_BLENDTBL_RMSSI_HI);
}
}
- clear_all_bit(blend_tbl_mask_flag);
- hal->jni_cb->fm_get_blend_cb(val, status);
+
+ if (!hal->set_cmd_sent)
+ hal->jni_cb->fm_get_blend_cb(val, status);
+ else {
+ pthread_mutex_lock(&hal->cmd_lock);
+ pthread_cond_broadcast(&hal->cmd_cond);
+ pthread_mutex_unlock(&hal->cmd_lock);
+ }
}
static void hci_cc_set_blend_tbl_rsp(char *ev_buff)
@@ -1167,6 +1199,59 @@ int set_low_power_mode(int lp_mode)
return retval;
}
+static int helium_send_hci_cmd(int cmd, void *cmd_param)
+{
+ int ret = FM_HC_STATUS_FAIL;
+ struct timespec ts;
+ struct hci_fm_default_data_read_req *rd;
+
+ pthread_mutex_lock(&(hal->cmd_lock));
+ hal->set_cmd_sent = true;
+ switch (cmd) {
+ case HCI_FM_HELIUM_SINR_SAMPLES:
+ case HCI_FM_HELIUM_SINR_THRESHOLD:
+ case HCI_FM_HELIUM_INTF_LOW_THRESHOLD:
+ case HCI_FM_HELIUM_INTF_HIGH_THRESHOLD:
+ ret = hci_fm_get_ch_det_th();
+ break;
+ case HCI_FM_HELIUM_SINRFIRSTSTAGE:
+ case HCI_FM_HELIUM_RMSSIFIRSTSTAGE:
+ case HCI_FM_HELIUM_CF0TH12:
+ case HCI_FM_HELIUM_SRCHALGOTYPE:
+ case HCI_FM_HELIUM_AF_RMSSI_TH:
+ case HCI_FM_HELIUM_GOOD_CH_RMSSI_TH:
+ case HCI_FM_HELIUM_AF_RMSSI_SAMPLES:
+ case HCI_FM_HELIUM_RXREPEATCOUNT:
+ case HCI_FM_HELIUM_AF_ALGO:
+ case HCI_FM_HELIUM_AF_SINR_GD_CH_TH:
+ case HCI_FM_HELIUM_AF_SINR_TH:
+ rd = (struct hci_fm_default_data_read_req *) cmd_param;
+ ret = hci_fm_default_data_read_req(rd);
+ break;
+ case HCI_FM_HELIUM_BLEND_SINRHI:
+ ret = hci_fm_get_blend_req();
+ break;
+ case HCI_FM_HELIUM_BLEND_RMSSIHI:
+ ret = hci_fm_get_blend_req();
+ break;
+ }
+ if (ret == FM_HC_STATUS_SUCCESS) {
+ if ((ret = clock_gettime(CLOCK_REALTIME, &ts)) == 0) {
+ ts.tv_sec += HELIUM_CMD_TIME_OUT;
+ ALOGD("%s:waiting for cmd %d response ", LOG_TAG, cmd);
+ ret = pthread_cond_timedwait(&hal->cmd_cond, &hal->cmd_lock,
+ &ts);
+ ALOGD("%s: received %d cmd response.", LOG_TAG, cmd);
+ } else {
+ ALOGE("%s: clock gettime failed. err = %d(%s)", LOG_TAG,
+ errno, strerror(errno));
+ }
+ }
+ hal->set_cmd_sent = false;
+ pthread_mutex_unlock(&hal->cmd_lock);
+
+ return ret;
+}
/* Callback function to be registered with FM-HCI for event notification */
static struct fm_hci_callbacks_t hal_cb = {
@@ -1191,6 +1276,11 @@ int hal_init(fm_hal_callbacks_t *cb)
}
memset(hal, 0, sizeof(struct fm_hal_t));
hal->jni_cb = cb;
+
+ pthread_mutex_init(&hal->cmd_lock, NULL);
+ pthread_cond_init(&hal->cmd_cond, NULL);
+ hal->set_cmd_sent = false;
+
hal->radio = malloc(sizeof(struct radio_helium_device));
if (!hal->radio) {
ALOGE("%s:Failed to allocate memory for device", __func__);
@@ -1220,6 +1310,8 @@ out:
hal->radio = NULL;
}
hal->jni_cb = NULL;
+ pthread_cond_destroy(&hal->cmd_cond);
+ pthread_mutex_destroy(&hal->cmd_lock);
free(hal);
hal = NULL;
}
@@ -1235,6 +1327,7 @@ static int set_fm_ctrl(int cmd, int val)
unsigned int rds_grps_proc = 0;
char *data;
struct hci_fm_def_data_wr_req def_data_wrt;
+ struct hci_fm_def_data_rd_req def_data_rd;
if (!hal) {
ALOGE("%s:ALERT: command sent before hal init", __func__);
@@ -1522,7 +1615,12 @@ static int set_fm_ctrl(int cmd, int val)
ret = -1;
goto end;
}
- hal->radio->ch_det_threshold.sinr_samples = val;
+ ret = helium_send_hci_cmd(cmd, NULL);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
+ hal->radio->ch_det_threshold.sinr_samples = (char)val;
ret = set_ch_det_thresholds_req(&hal->radio->ch_det_threshold);
if (ret < 0) {
ALOGE("Failed to set SINR samples %d", ret);
@@ -1535,7 +1633,12 @@ static int set_fm_ctrl(int cmd, int val)
ret = -1;
goto end;
}
- hal->radio->ch_det_threshold.sinr = val;
+ ret = helium_send_hci_cmd(cmd, NULL);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
+ hal->radio->ch_det_threshold.sinr = (char)val;
ret = set_ch_det_thresholds_req(&hal->radio->ch_det_threshold);
break;
case HCI_FM_HELIUM_INTF_LOW_THRESHOLD:
@@ -1544,7 +1647,12 @@ static int set_fm_ctrl(int cmd, int val)
ret = -1;
goto end;
}
- hal->radio->ch_det_threshold.low_th = val;
+ ret = helium_send_hci_cmd(cmd, NULL);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
+ hal->radio->ch_det_threshold.low_th = (char)val;
ret = set_ch_det_thresholds_req(&hal->radio->ch_det_threshold);
break;
case HCI_FM_HELIUM_INTF_HIGH_THRESHOLD:
@@ -1553,10 +1661,25 @@ static int set_fm_ctrl(int cmd, int val)
ret = -1;
goto end;
}
- hal->radio->ch_det_threshold.high_th = val;
+ ret = helium_send_hci_cmd(cmd, NULL);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
+ hal->radio->ch_det_threshold.high_th = (char)val;
ret = set_ch_det_thresholds_req(&hal->radio->ch_det_threshold);
break;
case HCI_FM_HELIUM_SINRFIRSTSTAGE:
+ def_data_rd.mode = FM_SRCH_CONFG_MODE;
+ def_data_rd.length = FM_SRCH_CNFG_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = FM_SRCH_CONFG_MODE;
def_data_wrt.length = FM_SRCH_CNFG_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1565,6 +1688,16 @@ static int set_fm_ctrl(int cmd, int val)
ret = hci_fm_default_data_write_req(&def_data_wrt);
break;
case HCI_FM_HELIUM_RMSSIFIRSTSTAGE:
+ def_data_rd.mode = FM_SRCH_CONFG_MODE;
+ def_data_rd.length = FM_SRCH_CNFG_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = FM_SRCH_CONFG_MODE;
def_data_wrt.length = FM_SRCH_CNFG_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1573,6 +1706,16 @@ static int set_fm_ctrl(int cmd, int val)
ret = hci_fm_default_data_write_req(&def_data_wrt);
break;
case HCI_FM_HELIUM_CF0TH12:
+ def_data_rd.mode = FM_SRCH_CONFG_MODE;
+ def_data_rd.length = FM_SRCH_CNFG_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = FM_SRCH_CONFG_MODE;
def_data_wrt.length = FM_SRCH_CNFG_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1582,6 +1725,16 @@ static int set_fm_ctrl(int cmd, int val)
ret = hci_fm_default_data_write_req(&def_data_wrt);
break;
case HCI_FM_HELIUM_SRCHALGOTYPE:
+ def_data_rd.mode = FM_SRCH_CONFG_MODE;
+ def_data_rd.length = FM_SRCH_CNFG_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = FM_SRCH_CONFG_MODE;
def_data_wrt.length = FM_SRCH_CNFG_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1590,6 +1743,16 @@ static int set_fm_ctrl(int cmd, int val)
ret = hci_fm_default_data_write_req(&def_data_wrt);
break;
case HCI_FM_HELIUM_AF_RMSSI_TH:
+ def_data_rd.mode = FM_AFJUMP_CONFG_MODE;
+ def_data_rd.length = FM_AFJUMP_CNFG_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = FM_AFJUMP_CONFG_MODE;
def_data_wrt.length = FM_AFJUMP_CNFG_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1598,6 +1761,16 @@ static int set_fm_ctrl(int cmd, int val)
ret = hci_fm_default_data_write_req(&def_data_wrt);
break;
case HCI_FM_HELIUM_GOOD_CH_RMSSI_TH:
+ def_data_rd.mode = FM_AFJUMP_CONFG_MODE;
+ def_data_rd.length = FM_AFJUMP_CNFG_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = FM_AFJUMP_CONFG_MODE;
def_data_wrt.length = FM_AFJUMP_CNFG_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1606,6 +1779,16 @@ static int set_fm_ctrl(int cmd, int val)
ret = hci_fm_default_data_write_req(&def_data_wrt);
break;
case HCI_FM_HELIUM_AF_RMSSI_SAMPLES:
+ def_data_rd.mode = FM_AFJUMP_CONFG_MODE;
+ def_data_rd.length = FM_AFJUMP_CNFG_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = FM_AFJUMP_CONFG_MODE;
def_data_wrt.length = FM_AFJUMP_CNFG_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1614,6 +1797,16 @@ static int set_fm_ctrl(int cmd, int val)
ret = hci_fm_default_data_write_req(&def_data_wrt);
break;
case HCI_FM_HELIUM_RXREPEATCOUNT:
+ def_data_rd.mode = RDS_PS0_XFR_MODE;
+ def_data_rd.length = RDS_PS0_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = RDS_PS0_XFR_MODE;
def_data_wrt.length = RDS_PS0_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1622,6 +1815,16 @@ static int set_fm_ctrl(int cmd, int val)
ret = hci_fm_default_data_write_req(&def_data_wrt);
break;
case HCI_FM_HELIUM_AF_ALGO:
+ def_data_rd.mode = FM_AFJUMP_CONFG_MODE;
+ def_data_rd.length = FM_AFJUMP_CNFG_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = FM_AFJUMP_CONFG_MODE;
def_data_wrt.length = FM_AFJUMP_CNFG_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1630,6 +1833,16 @@ static int set_fm_ctrl(int cmd, int val)
ret = hci_fm_default_data_write_req(&def_data_wrt);
break;
case HCI_FM_HELIUM_AF_SINR_GD_CH_TH:
+ def_data_rd.mode = FM_AFJUMP_CONFG_MODE;
+ def_data_rd.length = FM_AFJUMP_CNFG_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = FM_AFJUMP_CONFG_MODE;
def_data_wrt.length = FM_AFJUMP_CNFG_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1638,6 +1851,16 @@ static int set_fm_ctrl(int cmd, int val)
ret = hci_fm_default_data_write_req(&def_data_wrt);
break;
case HCI_FM_HELIUM_AF_SINR_TH:
+ def_data_rd.mode = FM_AFJUMP_CONFG_MODE;
+ def_data_rd.length = FM_AFJUMP_CNFG_LEN;
+ def_data_rd.param_len = 0;
+ def_data_rd.param = 0;
+
+ ret = helium_send_hci_cmd(cmd, (void *)&def_data_rd);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
def_data_wrt.mode = FM_AFJUMP_CONFG_MODE;
def_data_wrt.length = FM_AFJUMP_CNFG_LEN;
memcpy(&def_data_wrt.data, &hal->radio->def_data.data,
@@ -1651,7 +1874,13 @@ static int set_fm_ctrl(int cmd, int val)
ret = -1;
goto end;
}
- hal->radio->blend_tbl.BlendSinrHi = val;
+ ret = helium_send_hci_cmd(cmd, NULL);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
+
+ hal->radio->blend_tbl.BlendSinrHi = (char)val;
ret = hci_fm_set_blend_tbl_req(&hal->radio->blend_tbl);
break;
case HCI_FM_HELIUM_BLEND_RMSSIHI:
@@ -1660,13 +1889,19 @@ static int set_fm_ctrl(int cmd, int val)
ret = -1;
goto end;
}
- hal->radio->blend_tbl.BlendRmssiHi = val;
+ ret = helium_send_hci_cmd(cmd, NULL);
+ if (ret != FM_HC_STATUS_SUCCESS) {
+ ALOGE("%s: 0x%x cmd failed", LOG_TAG, cmd);
+ goto end;
+ }
+
+ hal->radio->blend_tbl.BlendRmssiHi = (char)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);
if (!(ret = hci_fm_enable_lpf(val))) {
- ALOGI("%s: command sent sucessfully", __func__, val);
+ ALOGI("%s: command sent sucessfully", __func__);
}
break;
case HCI_FM_HELIUM_AUDIO:
@@ -1680,7 +1915,7 @@ static int set_fm_ctrl(int cmd, int val)
}
end:
if (ret < 0)
- ALOGE("%s:%s: %d cmd failed", LOG_TAG, __func__, cmd);
+ ALOGE("%s:%s: 0x%x cmd failed", LOG_TAG, __func__, cmd);
return ret;
}
@@ -1813,6 +2048,7 @@ cmd:
ret = hci_fm_get_blend_req();
if (ret != FM_HC_STATUS_SUCCESS)
clear_bit(blend_tbl_mask_flag, CMD_BLENDTBL_SINR_HI);
+ break;
case HCI_FM_HELIUM_BLEND_RMSSIHI:
set_bit(blend_tbl_mask_flag, CMD_BLENDTBL_RMSSI_HI);
ret = hci_fm_get_blend_req();