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/helium/radio-helium-commands.h b/helium/radio-helium-commands.h
index c480ea0..f76b7d2 100644
--- a/helium/radio-helium-commands.h
+++ b/helium/radio-helium-commands.h
@@ -76,6 +76,22 @@
HCI_FM_HELIUM_DO_CALIBRATION,
HCI_FM_HELIUM_SRCH_ALGORITHM,
HCI_FM_HELIUM_GET_SINR,
+ HCI_FM_HELIUM_INTF_LOW_THRESHOLD,
+ HCI_FM_HELIUM_INTF_HIGH_THRESHOLD,
+ HCI_FM_HELIUM_SINR_THRESHOLD,
+ HCI_FM_HELIUM_SINR_SAMPLES,
+ HCI_FM_HELIUM_SPUR_FREQ,
+ HCI_FM_HELIUM_SPUR_FREQ_RMSSI,
+ HCI_FM_HELIUM_SPUR_SELECTION,
+ HCI_FM_HELIUM_UPDATE_SPUR_TABLE,
+ HCI_FM_HELIUM_VALID_CHANNEL,
+ HCI_FM_HELIUM_AF_RMSSI_TH,
+ HCI_FM_HELIUM_AF_RMSSI_SAMPLES,
+ HCI_FM_HELIUM_GOOD_CH_RMSSI_TH,
+ HCI_FM_HELIUM_SRCHALGOTYPE,
+ HCI_FM_HELIUM_CF0TH12,
+ HCI_FM_HELIUM_SINRFIRSTSTAGE,
+ HCI_FM_HELIUM_RMSSIFIRSTSTAGE,
HCI_FM_HELIUM_RXREPEATCOUNT,
HCI_FM_HELIUM_RSSI_TH,
HCI_FM_HELIUM_AF_JUMP_RSSI_TH,
diff --git a/helium/radio-helium.h b/helium/radio-helium.h
index 8599316..5c21bdd 100644
--- a/helium/radio-helium.h
+++ b/helium/radio-helium.h
@@ -160,6 +160,9 @@
typedef void (*disable_cb)();
typedef void (*callback_thread_event)(unsigned int evt);
typedef void (*rds_grp_cntrs_cb)(char *rds_params);
+typedef void (*fm_peek_cb)(char *peek_rsp);
+typedef void (*fm_ssbi_peek_cb)(char *ssbi_peek_rsp);
+typedef void (*fm_ch_det_th_cb)(char *ch_det_rsp);
typedef struct {
size_t size;
@@ -179,6 +182,9 @@
ert_cb ert_update_cb;
disable_cb disabled_cb;
rds_grp_cntrs_cb rds_grp_cntrs_rsp_cb;
+ fm_peek_cb fm_peek_rsp_cb;
+ fm_ssbi_peek_cb fm_ssbi_peek_rsp_cb;
+ fm_ch_det_th_cb fm_ch_det_th_rsp_cb;
callback_thread_event thread_evt_cb;
} fm_vendor_callbacks_t;
@@ -499,7 +505,6 @@
#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
#define HCI_REQ_CANCELED 2
@@ -1157,5 +1162,34 @@
enum hlm_region_t region;
struct hci_fm_dbg_param_rsp st_dbg_param;
struct hci_ev_srch_list_compl srch_st_result;
+ struct hci_fm_riva_poke riva_data_req;
+ struct hci_fm_ssbi_req ssbi_data_accs;
+ struct hci_fm_ssbi_peek ssbi_peek_reg;
+ struct hci_fm_ch_det_threshold ch_det_threshold;
};
+int hci_fm_disable_recv_req();
+int helium_search_list(struct hci_fm_search_station_list_req *s_list);
+int helium_search_rds_stations(struct hci_fm_search_rds_station_req *rds_srch);
+int helium_search_stations(struct hci_fm_search_station_req *srch);
+int helium_cancel_search_req();
+int hci_fm_set_recv_conf_req (struct hci_fm_recv_conf_req *conf);
+int hci_fm_get_program_service_req ();
+int hci_fm_get_rds_grpcounters_req (int val);
+int hci_fm_set_notch_filter_req (int val);
+int helium_set_sig_threshold_req(char th);
+int helium_rds_grp_mask_req(struct hci_fm_rds_grp_req *rds_grp_msk);
+int helium_rds_grp_process_req(int rds_grp);
+int helium_set_event_mask_req(char e_mask);
+int helium_set_antenna_req(char ant);
+int helium_set_fm_mute_mode_req(struct hci_fm_mute_mode_req *mute);
+int hci_fm_tune_station_req(int param);
+int hci_set_fm_stereo_mode_req(struct hci_fm_stereo_mode_req *param);
+int hci_peek_data(struct hci_fm_riva_data *data);
+int hci_poke_data(struct hci_fm_riva_poke *data);
+int hci_ssbi_poke_reg(struct hci_fm_ssbi_req *data);
+int hci_ssbi_peek_reg(struct hci_fm_ssbi_peek *data);
+int hci_fm_get_ch_det_th();
+int set_ch_det_thresholds_req(struct hci_fm_ch_det_threshold *ch_det_th);
+
+
#endif /* __UAPI_RADIO_HCI_CORE_H */
diff --git a/helium/radio_helium_hal.c b/helium/radio_helium_hal.c
index a9aa9f0..fd673ab 100644
--- a/helium/radio_helium_hal.c
+++ b/helium/radio_helium_hal.c
@@ -29,6 +29,8 @@
#include <stdio.h>
#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
#include <utils/Log.h>
#include "radio-helium-commands.h"
#include "radio-helium.h"
@@ -38,6 +40,7 @@
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;
@@ -98,14 +101,18 @@
ALOGE("%s:%s, buffer is null\n", LOG_TAG, __func__);
return;
}
+ ALOGE("%s:enetred %s calling ", LOG_TAG, __func__);
status = (char) *ev_buff;
radio_hci_req_complete(status);
if (radio->mode == FM_TURNING_OFF) {
jni_cb->disabled_cb();
radio->mode = FM_OFF;
+ jni_cb->disabled_cb();
+ jni_cb->thread_evt_cb(1);
//close the userial port and power off the chip
- fm_userial_close();
- fm_power(FM_RADIO_DISABLE);
+ ALOGE("%s:calling fm userial close\n", LOG_TAG );
+ fm_userial_close();
+ // fm_power(FM_RADIO_DISABLE);
}
}
@@ -138,6 +145,57 @@
jni_cb->rds_grp_cntrs_rsp_cb(&ev_buff[1]);
}
+static void hci_cc_riva_peek_rsp(char *ev_buff)
+{
+ char status;
+
+ if (ev_buff == NULL) {
+ ALOGE("%s:%s, buffer is null\n", LOG_TAG, __func__);
+ return;
+ }
+ status = ev_buff[0];
+ ALOGE("%s:%s, status =%d\n", LOG_TAG, __func__,status);
+ 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]);
+ radio_hci_req_complete(status);
+}
+
+static void hci_cc_ssbi_peek_rsp(char *ev_buff)
+{
+ char status;
+
+ if (ev_buff == NULL) {
+ ALOGE("%s:%s, buffer is null\n", LOG_TAG, __func__);
+ return;
+ }
+ status = ev_buff[0];
+ ALOGE("%s:%s, status =%d\n", LOG_TAG, __func__,status);
+ 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]);
+ radio_hci_req_complete(status);
+}
+
+static void hci_cc_get_ch_det_threshold_rsp(char *ev_buff)
+{
+ char status;
+
+ if (ev_buff == NULL) {
+ ALOGE("%s:%s, buffer is null\n", LOG_TAG, __func__);
+ return;
+ }
+ status = ev_buff[0];
+ ALOGE("%s:%s, status =%d\n", LOG_TAG, __func__,status);
+ if (status < 0) {
+ ALOGE("%s:%s,ssbi peek failed=%d\n", LOG_TAG, __func__, status);
+ }
+ memcpy(&radio->ch_det_threshold, &ev_buff[1],
+ sizeof(struct hci_fm_ch_det_threshold));
+ radio_hci_req_complete(status);
+}
static inline void hci_cmd_complete_event(char *buff)
{
@@ -192,12 +250,18 @@
case hci_status_param_op_pack(HCI_OCF_FM_READ_GRP_COUNTERS):
hci_cc_rds_grp_cntrs_rsp(pbuf);
break;
-/* case hci_common_cmd_op_pack(HCI_OCF_FM_GET_SPUR_TABLE):
- hci_cc_get_spur_tbl(buff);
+ case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_PEEK_DATA):
+ hci_cc_riva_peek_rsp(buff);
break;
case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_SSBI_PEEK_REG):
hci_cc_ssbi_peek_rsp(buff);
break;
+ case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_CH_DET_THRESHOLD):
+ hci_cc_get_ch_det_threshold_rsp(buff);
+ break;
+/* case hci_common_cmd_op_pack(HCI_OCF_FM_GET_SPUR_TABLE):
+ hci_cc_get_spur_tbl(buff);
+ break;
case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_SIGNAL_THRESHOLD):
hci_cc_sig_threshold_rsp(buff);
break;
@@ -222,10 +286,6 @@
hci_cc_riva_read_default_rsp(buff);
break;
- case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_PEEK_DATA):
- hci_cc_riva_peek_rsp(buff);
- break;
-
case hci_common_cmd_op_pack(HCI_OCF_FM_GET_FEATURE_LIST):
hci_cc_feature_list_rsp(buff);
break;
@@ -240,9 +300,6 @@
hci_cc_do_calibration_rsp(buff);
break;
- case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_CH_DET_THRESHOLD):
- hci_cc_get_ch_det_threshold_rsp(buff);
- break;
case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_BLND_TBL):
hci_cc_get_blend_tbl_rsp(buff);
break;
@@ -364,6 +421,7 @@
while ((buff[len+RDS_OFFSET] != 0x0d) && (len < MAX_RT_LENGTH))
len++;
+ ALOGV("%s:%s: radio text length=%d\n", LOG_TAG, __func__,len);
data = malloc(len+RDS_OFFSET);
if (!data) {
ALOGE("%s:Failed to allocate memory", LOG_TAG);
@@ -521,7 +579,8 @@
{
ALOGE("%s:%s: start", LOG_TAG, __func__);
jni_cb->disabled_cb();
- fm_userial_close();
+ jni_cb->thread_evt_cb(1);
+ fm_userial_close();
}
static void hci_buff_ert(struct rds_grp_data *rds_buf)
@@ -646,7 +705,7 @@
// hci_ev_rt_plus(temp);
}
else if (carrier == ert_carrier) {
- ALOGE("%s:: calling event ert", __func__);
+ ALOGI("%s:: calling event ert", __func__);
hci_buff_ert(&temp);
}
}
@@ -711,9 +770,9 @@
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;
+ case HCI_EV_HW_ERR_EVENT:
+ hci_ev_hw_error(((FM_EVT_HDR *)evt_buf)->cmd_params);
+ break;
default:
break;
}
@@ -1063,6 +1122,125 @@
radio->stereo_mode.stereo_mode = ~val;
hci_set_fm_stereo_mode_req(&radio->stereo_mode);
break;
+ case HCI_FM_HELIUM_RIVA_ACCS_ADDR:
+ 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;
+ } else {
+ ret = -1;
+ ALOGE("%s: riva access len is not valid\n", LOG_TAG);
+ goto END;
+ }
+ 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);
+ break;
+ case HCI_FM_HELIUM_RIVA_POKE:
+ if (radio->riva_data_req.cmd_params.length <=
+ MAX_RIVA_PEEK_RSP_SIZE) {
+ radio->riva_data_req.cmd_params.subopcode =
+ RIVA_POKE_OPCODE;
+ ret = hci_poke_data(&radio->riva_data_req);
+ } else {
+ ALOGE("%s: riva access len is not valid for poke\n", LOG_TAG);
+ ret = -1;
+ goto END;
+ }
+ break;
+ case HCI_FM_HELIUM_SSBI_ACCS_ADDR:
+ 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);
+ break;
+ case HCI_FM_HELIUM_SSBI_PEEK:
+ radio->ssbi_peek_reg.start_address = val;
+ hci_ssbi_peek_reg(&radio->ssbi_peek_reg);
+ break;
+ case HCI_FM_HELIUM_SINR_SAMPLES:
+ if (!is_valid_sinr_samples(val)) {
+ ALOGE("%s: sinr samples count is not valid\n", __func__);
+ ret = -1;
+ goto END;
+ }
+ ret = hci_fm_get_ch_det_th();
+ if (ret < 0) {
+ ALOGE("Failed to get chnl det thresholds %d", ret);
+ goto END;
+ }
+ saved_val = radio->ch_det_threshold.sinr_samples;
+ radio->ch_det_threshold.sinr_samples = val;
+ ret = set_ch_det_thresholds_req(&radio->ch_det_threshold);
+ if (ret < 0) {
+ ALOGE("Failed to set SINR samples %d", ret);
+ radio->ch_det_threshold.sinr_samples = saved_val;
+ goto END;
+ }
+ break;
+ case HCI_FM_HELIUM_SINR_THRESHOLD:
+ if (!is_valid_sinr_th(val)) {
+ ALOGE("%s: sinr threshold is not valid\n");
+ ret = -1;
+ goto END;
+ }
+ ret = hci_fm_get_ch_det_th();
+ if (ret < 0) {
+ ALOGE("Failed to get chnl det thresholds %d", ret);
+ goto END;
+ }
+ saved_val = radio->ch_det_threshold.sinr;
+ radio->ch_det_threshold.sinr = val;
+ ret = set_ch_det_thresholds_req(&radio->ch_det_threshold);
+ if (ret < 0) {
+ ALOGE("Failed to set SINR threshold %d", ret);
+ radio->ch_det_threshold.sinr = saved_val;
+ goto END;
+ }
+ break;
+ case HCI_FM_HELIUM_INTF_LOW_THRESHOLD:
+ if (!is_valid_intf_det_low_th(val)) {
+ ALOGE("%s: intf det low threshold is not valid\n", __func__);
+ ret = -1;
+ goto END;
+ }
+ ret = hci_fm_get_ch_det_th();
+ if (ret < 0) {
+ ALOGE("Failed to get chnl det thresholds %d", ret);
+ goto END;
+ }
+ saved_val = radio->ch_det_threshold.low_th;
+ radio->ch_det_threshold.low_th = val;
+ ret = set_ch_det_thresholds_req(&radio->ch_det_threshold);
+ if (ret < 0) {
+ ALOGE("Failed to Set Low det threshold %d", ret);
+ radio->ch_det_threshold.low_th = saved_val;
+ goto END;
+ }
+ break;
+ case HCI_FM_HELIUM_INTF_HIGH_THRESHOLD:
+ if (!is_valid_intf_det_hgh_th(val)) {
+ ALOGE("%s: intf high threshold is not valid\n", __func__);
+ ret = -1;
+ goto END;
+ }
+ ret = hci_fm_get_ch_det_th();
+ if (ret < 0) {
+ ALOGE("Failed to get chnl det thresholds %d", ret);
+ goto END;
+ }
+ saved_val = radio->ch_det_threshold.high_th;
+ radio->ch_det_threshold.high_th = val;
+ ret = set_ch_det_thresholds_req(&radio->ch_det_threshold);
+ if (ret < 0) {
+ ALOGE("Failed to set High det threshold %d ", ret);
+ radio->ch_det_threshold.high_th = saved_val;
+ goto END;
+ }
+ break;
default:
ALOGE("%s:%s: Not a valid FM CMD!!", LOG_TAG, __func__);
ret = 0;
@@ -1088,6 +1266,26 @@
case HCI_FM_HELIUM_LOWER_BAND:
val = radio->recv_conf.band_low_limit;
break;
+ case HCI_FM_HELIUM_SINR_SAMPLES:
+ ret = hci_fm_get_ch_det_th();
+ if (ret == 0)
+ val = radio->ch_det_threshold.sinr_samples;
+ break;
+ case HCI_FM_HELIUM_SINR_THRESHOLD:
+ ret = hci_fm_get_ch_det_th();
+ if (ret == 0)
+ val = radio->ch_det_threshold.sinr;
+ break;
+ case HCI_FM_HELIUM_INTF_LOW_THRESHOLD:
+ ret = hci_fm_get_ch_det_th();
+ if (ret == 0)
+ val = radio->ch_det_threshold.low_th;
+ break;
+ case HCI_FM_HELIUM_INTF_HIGH_THRESHOLD:
+ ret = hci_fm_get_ch_det_th();
+ if (ret == 0)
+ val = radio->ch_det_threshold.high_th;
+ break;
default:
break;
}
diff --git a/helium/radio_helium_hal_cmds.c b/helium/radio_helium_hal_cmds.c
index 1d422d1..df79d75 100644
--- a/helium/radio_helium_hal_cmds.c
+++ b/helium/radio_helium_hal_cmds.c
@@ -29,6 +29,9 @@
#include <stdio.h>
#include <utils/Log.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
#include "radio-helium-commands.h"
#include "radio-helium.h"
#include "fm_hci.h"
@@ -282,3 +285,74 @@
stereo_mode_req);
}
+int hci_peek_data(struct hci_fm_riva_data *data)
+{
+ uint16_t opcode = 0;
+
+ if (data == NULL) {
+ ALOGE("%s:%s, peek data req is null\n", LOG_TAG, __func__);
+ return -1;
+ }
+ opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
+ HCI_OCF_FM_PEEK_DATA);
+ return send_fm_cmd_pkt(opcode, sizeof((*data)), data);
+}
+
+int hci_poke_data(struct hci_fm_riva_poke *data)
+{
+ uint16_t opcode = 0;
+
+ if (data == NULL) {
+ ALOGE("%s:%s, poke data req is null\n", LOG_TAG, __func__);
+ return -1;
+ }
+ opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
+ HCI_OCF_FM_POKE_DATA);
+ return send_fm_cmd_pkt(opcode, sizeof((*data)), data);
+}
+
+int hci_ssbi_poke_reg(struct hci_fm_ssbi_req *data)
+{
+ uint16_t opcode = 0;
+
+ if (data == NULL) {
+ ALOGE("%s:%s,SSBI poke data req is null\n", LOG_TAG, __func__);
+ return -1;
+ }
+ opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
+ HCI_OCF_FM_SSBI_POKE_REG);
+ return send_fm_cmd_pkt(opcode, sizeof((*data)), data);
+}
+
+int hci_ssbi_peek_reg(struct hci_fm_ssbi_peek *data)
+{
+ uint16_t opcode = 0;
+
+ if (data == NULL) {
+ ALOGE("%s:%s,SSBI peek data req is null\n", LOG_TAG, __func__);
+ return -1;
+ }
+ opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
+ HCI_OCF_FM_SSBI_PEEK_REG);
+ return send_fm_cmd_pkt(opcode, sizeof((*data)), data);
+}
+
+int hci_fm_get_ch_det_th()
+{
+ uint16_t opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+ HCI_OCF_FM_GET_CH_DET_THRESHOLD);
+ return send_fm_cmd_pkt(opcode, 0, NULL);
+}
+
+int set_ch_det_thresholds_req(struct hci_fm_ch_det_threshold *ch_det_th)
+{
+ uint16_t opcode = 0;
+
+ if (ch_det_th == NULL) {
+ ALOGE("%s,%s channel det thrshld is null\n", LOG_TAG, __func__);
+ return -1;
+ }
+ opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+ HCI_OCF_FM_SET_CH_DET_THRESHOLD);
+ return send_fm_cmd_pkt(opcode, sizeof((*ch_det_th)), ch_det_th);
+}