Merge "radio: iris: Bound check user space values"
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 188673d..9f18508 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -2391,6 +2391,7 @@
struct sk_buff *skb)
{
struct iris_device *radio = video_get_drvdata(video_get_dev());
+ radio->search_on = 0;
iris_q_event(radio, IRIS_EVT_SEEK_COMPLETE);
}
@@ -2920,6 +2921,7 @@
{
int retval = 0;
enum search_t srch;
+ int saved_val;
if (unlikely(radio == NULL)) {
FMDERR(":radio is null");
@@ -2927,6 +2929,7 @@
}
srch = radio->g_search_mode & SRCH_MODE;
+ saved_val = radio->search_on;
radio->search_on = on;
if (on) {
switch (srch) {
@@ -2961,6 +2964,8 @@
retval = hci_cmd(HCI_FM_CANCEL_SEARCH_CMD, radio->fm_hdev);
}
+ if (retval < 0)
+ radio->search_on = saved_val;
return retval;
}
@@ -3013,18 +3018,22 @@
static int iris_recv_set_region(struct iris_device *radio, int req_region)
{
int retval;
+ int saved_val;
if (unlikely(radio == NULL)) {
FMDERR(":radio is null");
return -EINVAL;
}
-
+ saved_val = radio->region;
radio->region = req_region;
retval = hci_set_fm_recv_conf(
&radio->recv_conf,
radio->fm_hdev);
+ if (retval < 0)
+ radio->region = saved_val;
+
return retval;
}
@@ -3032,16 +3041,22 @@
static int iris_trans_set_region(struct iris_device *radio, int req_region)
{
int retval;
+ int saved_val;
if (unlikely(radio == NULL)) {
FMDERR(":radio is null");
return -EINVAL;
}
+
+ saved_val = radio->region;
radio->region = req_region;
retval = hci_set_fm_trans_conf(
&radio->trans_conf,
radio->fm_hdev);
+
+ if (retval < 0)
+ radio->region = saved_val;
return retval;
}
@@ -3129,30 +3144,44 @@
if (unlikely(radio == NULL)) {
FMDERR(":radio is null");
- return -EINVAL;
+ retval = -EINVAL;
+ goto END;
}
if (unlikely(ctrl == NULL)) {
FMDERR("%s, v4l2 ctrl is null\n", __func__);
- return -EINVAL;
+ retval = -EINVAL;
+ goto END;
}
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME:
break;
case V4L2_CID_AUDIO_MUTE:
- ctrl->value = radio->mute_mode.hard_mute;
+ if (is_valid_hard_mute(radio->mute_mode.hard_mute))
+ ctrl->value = radio->mute_mode.hard_mute;
+ else
+ retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_IRIS_SRCHMODE:
- ctrl->value = radio->g_search_mode;
+ if (is_valid_srch_mode(radio->g_search_mode))
+ ctrl->value = radio->g_search_mode;
+ else
+ retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_IRIS_SCANDWELL:
- ctrl->value = radio->g_scan_time;
+ if (is_valid_scan_dwell_prd(radio->g_scan_time))
+ ctrl->value = radio->g_scan_time;
+ else
+ retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_IRIS_SRCHON:
ctrl->value = radio->search_on;
break;
case V4L2_CID_PRIVATE_IRIS_STATE:
- ctrl->value = radio->mode;
+ if (is_valid_fm_state(radio->mode))
+ ctrl->value = radio->mode;
+ else
+ retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_IRIS_IOVERC:
retval = hci_cmd(HCI_FM_STATION_DBG_PARAM_CMD, radio->fm_hdev);
@@ -3162,68 +3191,115 @@
break;
case V4L2_CID_PRIVATE_IRIS_INTDET:
retval = hci_cmd(HCI_FM_STATION_DBG_PARAM_CMD, radio->fm_hdev);
- if (retval < 0)
- return retval;
- ctrl->value = radio->st_dbg_param.in_det_out;
+ if (retval == 0)
+ ctrl->value = radio->st_dbg_param.in_det_out;
+ else
+ retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_IRIS_REGION:
ctrl->value = radio->region;
break;
case V4L2_CID_PRIVATE_IRIS_SIGNAL_TH:
retval = hci_cmd(HCI_FM_GET_SIGNAL_TH_CMD, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("Error in get signal threshold %d\n", retval);
- return retval;
- }
- ctrl->value = radio->sig_th.sig_threshold;
+ if ((retval == 0) &&
+ is_valid_sig_th(radio->sig_th.sig_threshold))
+ ctrl->value = radio->sig_th.sig_threshold;
+ else
+ retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_IRIS_SRCH_PTY:
- ctrl->value = radio->srch_rds.srch_pty;
+ if (is_valid_pty(radio->srch_rds.srch_pty))
+ ctrl->value = radio->srch_rds.srch_pty;
+ else
+ retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_IRIS_SRCH_PI:
- ctrl->value = radio->srch_rds.srch_pi;
+ if (is_valid_pi(radio->srch_rds.srch_pi))
+ ctrl->value = radio->srch_rds.srch_pi;
+ else
+ retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_IRIS_SRCH_CNT:
- ctrl->value = radio->srch_st_result.num_stations_found;
+ if (is_valid_srch_station_cnt(
+ radio->srch_st_result.num_stations_found))
+ ctrl->value = radio->srch_st_result.num_stations_found;
+ else
+ retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_IRIS_EMPHASIS:
if (radio->mode == FM_RECV) {
- ctrl->value = radio->recv_conf.emphasis;
+ retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+ radio->fm_hdev);
+ if ((retval == 0) &&
+ is_valid_emphasis(radio->recv_conf.emphasis))
+ ctrl->value = radio->recv_conf.emphasis;
+ else
+ retval = -EINVAL;
} else if (radio->mode == FM_TRANS) {
- ctrl->value = radio->trans_conf.emphasis;
+ retval = hci_cmd(HCI_FM_GET_TX_CONFIG,
+ radio->fm_hdev);
+ if ((retval == 0) &&
+ is_valid_emphasis(radio->trans_conf.emphasis))
+ ctrl->value = radio->trans_conf.emphasis;
+ else
+ retval = -EINVAL;
} else {
- FMDERR("Error in radio mode"
- " %d\n", retval);
- return -EINVAL;
+ retval = -EINVAL;
+ FMDERR("Error in radio mode"" %d\n", retval);
}
break;
case V4L2_CID_PRIVATE_IRIS_RDS_STD:
if (radio->mode == FM_RECV) {
- ctrl->value = radio->recv_conf.rds_std;
+ retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+ radio->fm_hdev);
+ if ((retval == 0) &&
+ is_valid_rds_std(radio->recv_conf.rds_std))
+ ctrl->value = radio->recv_conf.rds_std;
+ else
+ retval = -EINVAL;
} else if (radio->mode == FM_TRANS) {
- ctrl->value = radio->trans_conf.rds_std;
+ retval = hci_cmd(HCI_FM_GET_TX_CONFIG,
+ radio->fm_hdev);
+ if ((retval == 0) &&
+ is_valid_rds_std(radio->trans_conf.rds_std))
+ ctrl->value = radio->trans_conf.rds_std;
+ else
+ retval = -EINVAL;
} else {
+ retval = -EINVAL;
FMDERR("Error in radio mode"
" %d\n", retval);
- return -EINVAL;
}
break;
case V4L2_CID_PRIVATE_IRIS_SPACING:
if (radio->mode == FM_RECV) {
- ctrl->value = radio->recv_conf.ch_spacing;
+ retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+ radio->fm_hdev);
+ if ((retval == 0) &&
+ is_valid_chan_spacing(
+ radio->recv_conf.ch_spacing))
+ ctrl->value = radio->recv_conf.ch_spacing;
+ else
+ retval = -EINVAL;
} else {
+ retval = -EINVAL;
FMDERR("Error in radio mode"
" %d\n", retval);
- return -EINVAL;
}
break;
case V4L2_CID_PRIVATE_IRIS_RDSON:
if (radio->mode == FM_RECV) {
- ctrl->value = radio->recv_conf.rds_std;
+ retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+ radio->fm_hdev);
+ if ((retval == 0) &&
+ is_valid_rds_std(radio->recv_conf.rds_std))
+ ctrl->value = radio->recv_conf.rds_std;
+ else
+ retval = -EINVAL;
} else {
+ retval = -EINVAL;
FMDERR("Error in radio mode"
" %d\n", retval);
- return -EINVAL;
}
break;
case V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK:
@@ -3243,7 +3319,12 @@
ctrl->value = radio->g_antenna;
break;
case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
- ctrl->value = radio->mute_mode.soft_mute;
+ retval = hci_cmd(HCI_FM_STATION_DBG_PARAM_CMD, radio->fm_hdev);
+ if ((retval == 0) &&
+ is_valid_soft_mute(radio->mute_mode.soft_mute))
+ ctrl->value = radio->mute_mode.soft_mute;
+ else
+ retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_IRIS_DO_CALIBRATION:
retval = iris_do_calibration(radio);
@@ -3252,47 +3333,30 @@
if (radio->mode == FM_RECV) {
retval = hci_cmd(HCI_FM_GET_STATION_PARAM_CMD,
radio->fm_hdev);
- if (retval < 0) {
- FMDERR("Get SINR Failed");
- return retval;
- }
- ctrl->value = radio->fm_st_rsp.station_rsp.sinr;
-
+ if (retval == 0)
+ ctrl->value = radio->fm_st_rsp.station_rsp.sinr;
} else
retval = -EINVAL;
break;
case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("Get High det threshold failed %x", retval);
- return retval;
- }
- ctrl->value = radio->ch_det_threshold.high_th;
+ if (retval == 0)
+ ctrl->value = radio->ch_det_threshold.high_th;
break;
case V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD:
retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("Get Low det threshold failed %x", retval);
- return retval;
- }
- ctrl->value = radio->ch_det_threshold.low_th;
+ if (retval == 0)
+ ctrl->value = radio->ch_det_threshold.low_th;
break;
case V4L2_CID_PRIVATE_SINR_THRESHOLD:
retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("Get SINR threshold failed %x", retval);
- return retval;
- }
- ctrl->value = radio->ch_det_threshold.sinr;
+ if (retval == 0)
+ ctrl->value = radio->ch_det_threshold.sinr;
break;
case V4L2_CID_PRIVATE_SINR_SAMPLES:
retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("Get SINR samples failed %x", retval);
- return retval;
- }
-
- ctrl->value = radio->ch_det_threshold.sinr_samples;
+ if (retval == 0)
+ ctrl->value = radio->ch_det_threshold.sinr_samples;
break;
case V4L2_CID_PRIVATE_VALID_CHANNEL:
ctrl->value = radio->is_station_valid;
@@ -3304,13 +3368,11 @@
rd.param = 0;
retval = hci_def_data_read(&rd, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("Get AF Jump Threshold failed %x", retval);
- return retval;
+ if (retval == 0) {
+ lsb = radio->default_data.data[AF_RMSSI_TH_LSB_OFFSET];
+ msb = radio->default_data.data[AF_RMSSI_TH_MSB_OFFSET];
+ ctrl->value = ((msb << 8) | lsb);
}
- lsb = radio->default_data.data[AF_RMSSI_TH_LSB_OFFSET];
- msb = radio->default_data.data[AF_RMSSI_TH_MSB_OFFSET];
- ctrl->value = ((msb << 8) | lsb);
break;
case V4L2_CID_PRIVATE_AF_RMSSI_SAMPLES:
rd.mode = FM_RDS_CNFG_MODE;
@@ -3319,11 +3381,9 @@
rd.param = 0;
retval = hci_def_data_read(&rd, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("Get AF jump rmssi samples failed %x", retval);
- return retval;
- }
- ctrl->value = radio->default_data.data[AF_RMSSI_SAMPLES_OFFSET];
+ if (retval == 0)
+ ctrl->value =
+ radio->default_data.data[AF_RMSSI_SAMPLES_OFFSET];
break;
case V4L2_CID_PRIVATE_GOOD_CH_RMSSI_TH:
rd.mode = FM_RX_CONFG_MODE;
@@ -3332,13 +3392,12 @@
rd.param = 0;
retval = hci_def_data_read(&rd, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("get good channel rmssi th failed %x", retval);
- return retval;
+ if (retval == 0) {
+ ctrl->value =
+ radio->default_data.data[GD_CH_RMSSI_TH_OFFSET];
+ if (ctrl->value > MAX_GD_CH_RMSSI_TH)
+ ctrl->value -= 256;
}
- ctrl->value = radio->default_data.data[GD_CH_RMSSI_TH_OFFSET];
- if (ctrl->value > MAX_GD_CH_RMSSI_TH)
- ctrl->value -= 256;
break;
case V4L2_CID_PRIVATE_SRCHALGOTYPE:
rd.mode = FM_RX_CONFG_MODE;
@@ -3347,11 +3406,9 @@
rd.param = 0;
retval = hci_def_data_read(&rd, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("get search algo type failed %x", retval);
- return retval;
- }
- ctrl->value = radio->default_data.data[SRCH_ALGO_TYPE_OFFSET];
+ if (retval == 0)
+ ctrl->value =
+ radio->default_data.data[SRCH_ALGO_TYPE_OFFSET];
break;
case V4L2_CID_PRIVATE_SINRFIRSTSTAGE:
rd.mode = FM_RX_CONFG_MODE;
@@ -3360,13 +3417,12 @@
rd.param = 0;
retval = hci_def_data_read(&rd, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("default data read failed %x", retval);
- return retval;
+ if (retval == 0) {
+ ctrl->value =
+ radio->default_data.data[SINRFIRSTSTAGE_OFFSET];
+ if (ctrl->value > MAX_SINR_FIRSTSTAGE)
+ ctrl->value -= 256;
}
- ctrl->value = radio->default_data.data[SINRFIRSTSTAGE_OFFSET];
- if (ctrl->value > MAX_SINR_FIRSTSTAGE)
- ctrl->value -= 256;
break;
case V4L2_CID_PRIVATE_RMSSIFIRSTSTAGE:
rd.mode = FM_RX_CONFG_MODE;
@@ -3375,13 +3431,12 @@
rd.param = 0;
retval = hci_def_data_read(&rd, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("default data read failed %x", retval);
- return retval;
+ if (retval == 0) {
+ ctrl->value =
+ radio->default_data.data[RMSSIFIRSTSTAGE_OFFSET];
+ if (ctrl->value > MAX_RMSSI_FIRSTSTAGE)
+ ctrl->value -= 256;
}
- ctrl->value = radio->default_data.data[RMSSIFIRSTSTAGE_OFFSET];
- if (ctrl->value > MAX_RMSSI_FIRSTSTAGE)
- ctrl->value -= 256;
break;
case V4L2_CID_PRIVATE_CF0TH12:
rd.mode = FM_RX_CONFG_MODE;
@@ -3390,26 +3445,31 @@
rd.param = 0;
retval = hci_def_data_read(&rd, radio->fm_hdev);
- if (retval < 0) {
- FMDERR("default data read failed %x", retval);
- return retval;
+ if (retval == 0) {
+ ctrl->value =
+ radio->default_data.data[CF0TH12_BYTE1_OFFSET];
+ cf0 = radio->default_data.data[CF0TH12_BYTE2_OFFSET];
+ ctrl->value |= (cf0 << 8);
+ cf0 = radio->default_data.data[CF0TH12_BYTE3_OFFSET];
+ ctrl->value |= (cf0 << 16);
+ cf0 = radio->default_data.data[CF0TH12_BYTE4_OFFSET];
+ if (cf0 > 127)
+ cf0 -= 256;
+ ctrl->value |= (cf0 << 24);
}
- ctrl->value = radio->default_data.data[CF0TH12_BYTE1_OFFSET];
- cf0 = radio->default_data.data[CF0TH12_BYTE2_OFFSET];
- ctrl->value |= (cf0 << 8);
- cf0 = radio->default_data.data[CF0TH12_BYTE3_OFFSET];
- ctrl->value |= (cf0 << 16);
- cf0 = radio->default_data.data[CF0TH12_BYTE4_OFFSET];
- if (cf0 > 127)
- cf0 -= 256;
- ctrl->value |= (cf0 << 24);
break;
default:
retval = -EINVAL;
+ break;
}
+
+END:
+ if (retval > 0)
+ retval = -EINVAL;
if (retval < 0)
FMDERR("get control failed with %d, id: %d\n",
retval, ctrl->id);
+
return retval;
}
@@ -3423,27 +3483,36 @@
if (unlikely(radio == NULL)) {
FMDERR(":radio is null");
- return -EINVAL;
+ retval = -EINVAL;
+ goto END;
}
if (unlikely((ctrl == NULL)) || unlikely((ctrl->count == 0))
|| unlikely((ctrl->controls == NULL))) {
FMDERR("%s, invalid v4l2 ctrl\n", __func__);
- return -EINVAL;
+ retval = -EINVAL;
+ goto END;
}
switch ((ctrl->controls[0]).id) {
case V4L2_CID_PRIVATE_IRIS_READ_DEFAULT:
data = (ctrl->controls[0]).string;
memset(&default_data_rd, 0, sizeof(default_data_rd));
if (copy_from_user(&default_data_rd.mode, data,
- sizeof(default_data_rd)))
- return -EFAULT;
+ sizeof(default_data_rd))) {
+ retval = -EFAULT;
+ goto END;
+ }
retval = hci_def_data_read(&default_data_rd, radio->fm_hdev);
break;
default:
retval = -EINVAL;
+ break;
}
+END:
+ if (retval > 0)
+ retval = -EINVAL;
+
return retval;
}
@@ -3462,13 +3531,15 @@
if (unlikely(radio == NULL)) {
FMDERR(":radio is null");
- return -EINVAL;
+ retval = -EINVAL;
+ goto END;
}
if (unlikely((ctrl == NULL)) || unlikely((ctrl->count == 0))
|| unlikely((ctrl->controls == NULL))) {
FMDERR("%s, invalid v4l2 ctrl\n", __func__);
- return -EINVAL;
+ retval = -EINVAL;
+ goto END;
}
switch ((ctrl->controls[0]).id) {
@@ -3482,16 +3553,23 @@
data = (ctrl->controls[0]).string;
if (copy_from_user(tx_ps.ps_data,
- data, bytes_to_copy))
- return -EFAULT;
- tx_ps.ps_control = 0x01;
- tx_ps.pi = radio->pi;
- tx_ps.pty = radio->pty;
- tx_ps.ps_repeatcount = radio->ps_repeatcount;
- tx_ps.ps_num = (bytes_to_copy / PS_STRING_LEN);
+ data, bytes_to_copy)) {
+ FMDERR("%s: copy from user for tx ps name failed\n",
+ __func__);
+ retval = -EFAULT;
+ goto END;
+ } else {
+ tx_ps.ps_control = 0x01;
+ tx_ps.pi = radio->pi;
+ tx_ps.pty = radio->pty;
+ tx_ps.ps_repeatcount = radio->ps_repeatcount;
+ tx_ps.ps_num = (bytes_to_copy / PS_STRING_LEN);
- retval = radio_hci_request(radio->fm_hdev, hci_trans_ps_req,
- (unsigned long)&tx_ps, RADIO_HCI_TIMEOUT);
+ retval = radio_hci_request(radio->fm_hdev,
+ hci_trans_ps_req,
+ (unsigned long)&tx_ps,
+ RADIO_HCI_TIMEOUT);
+ }
break;
case V4L2_CID_RDS_TX_RADIO_TEXT:
bytes_to_copy =
@@ -3501,16 +3579,22 @@
memset(tx_rt.rt_data, 0, MAX_RT_LENGTH);
if (copy_from_user(tx_rt.rt_data,
- data, bytes_to_copy))
- return -EFAULT;
+ data, bytes_to_copy)) {
+ FMDERR("%s: copy from user for tx rt failed\n",
+ __func__);
+ retval = -EFAULT;
+ goto END;
+ } else {
+ tx_rt.rt_control = 0x01;
+ tx_rt.pi = radio->pi;
+ tx_rt.pty = radio->pty;
+ tx_rt.rt_len = bytes_to_copy;
- tx_rt.rt_control = 0x01;
- tx_rt.pi = radio->pi;
- tx_rt.pty = radio->pty;
- tx_rt.rt_len = bytes_to_copy;
-
- retval = radio_hci_request(radio->fm_hdev, hci_trans_rt_req,
- (unsigned long)&tx_rt, RADIO_HCI_TIMEOUT);
+ retval = radio_hci_request(radio->fm_hdev,
+ hci_trans_rt_req,
+ (unsigned long)&tx_rt,
+ RADIO_HCI_TIMEOUT);
+ }
break;
case V4L2_CID_PRIVATE_IRIS_WRITE_DEFAULT:
data = (ctrl->controls[0]).string;
@@ -3525,7 +3609,8 @@
*/
if (ctrl->controls[0].size > (DEFAULT_DATA_SIZE + 2)) {
pr_err("%s: Default data buffer overflow!\n", __func__);
- return -EINVAL;
+ retval = -EINVAL;
+ goto END;
}
/* copy only 'size' bytes of data as requested by user */
@@ -3534,7 +3619,8 @@
if (retval > 0) {
pr_err("%s: Failed to copy %d bytes of default data"
" passed by user\n", __func__, retval);
- return -EFAULT;
+ retval = -EFAULT;
+ goto END;
}
FMDBG("%s: XFR Mode\t: 0x%x\n", __func__, default_data.mode);
FMDBG("%s: XFR Data Length\t: %d\n", __func__,
@@ -3549,7 +3635,8 @@
if (default_data.length != (ctrl->controls[0].size - 2)) {
pr_err("%s: Invalid 'length' parameter passed for "
"actual xfr data\n", __func__);
- return -EINVAL;
+ retval = -EINVAL;
+ goto END;
}
retval = hci_def_data_write(&default_data, radio->fm_hdev);
break;
@@ -3558,24 +3645,32 @@
bytes_to_copy = (ctrl->controls[0]).size;
if (bytes_to_copy < PROCS_CALIB_SIZE) {
FMDERR("data is less than required size");
- return -EFAULT;
+ retval = -EFAULT;
+ goto END;
}
memset(proc_cal_req.data, 0, PROCS_CALIB_SIZE);
proc_cal_req.mode = PROCS_CALIB_MODE;
if (copy_from_user(&proc_cal_req.data[0],
- data, sizeof(proc_cal_req.data)))
- return -EFAULT;
+ data, sizeof(proc_cal_req.data))) {
+ retval = -EFAULT;
+ goto END;
+ }
retval = radio_hci_request(radio->fm_hdev,
hci_fm_set_cal_req_proc,
(unsigned long)&proc_cal_req,
RADIO_HCI_TIMEOUT);
- if (retval < 0)
- FMDERR("Set Process calibration failed %d", retval);
break;
default:
FMDBG("Shouldn't reach here\n");
retval = -1;
+ goto END;
+ break;
}
+
+END:
+ if (retval > 0)
+ retval = -EINVAL;
+
return retval;
}
@@ -3586,6 +3681,7 @@
int retval = 0;
unsigned int rds_grps_proc = 0;
__u8 temp_val = 0;
+ int saved_val;
unsigned long arg = 0;
struct hci_fm_tx_ps tx_ps = {0};
struct hci_fm_tx_rt tx_rt = {0};
@@ -3596,39 +3692,69 @@
if (unlikely(radio == NULL)) {
FMDERR(":radio is null");
- return -EINVAL;
+ retval = -EINVAL;
+ goto END;
}
if (unlikely(ctrl == NULL)) {
FMDERR("%s, v4l2 ctrl is null\n", __func__);
- return -EINVAL;
+ retval = -EINVAL;
+ goto END;
}
switch (ctrl->id) {
case V4L2_CID_PRIVATE_IRIS_TX_TONE:
+ if (!is_valid_tone(ctrl->value)) {
+ retval = -EINVAL;
+ FMDERR("%s: tone value is not valid\n", __func__);
+ goto END;
+ }
+ saved_val = radio->tone_freq;
radio->tone_freq = ctrl->value;
retval = radio_hci_request(radio->fm_hdev,
hci_fm_tone_generator, arg,
msecs_to_jiffies(RADIO_HCI_TIMEOUT));
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error while setting the tone %d", retval);
+ radio->tone_freq = saved_val;
+ }
break;
case V4L2_CID_AUDIO_VOLUME:
break;
case V4L2_CID_AUDIO_MUTE:
+ if (!is_valid_hard_mute(ctrl->value)) {
+ retval = -EINVAL;
+ FMDERR("%s: hard mute value is not valid\n", __func__);
+ goto END;
+ }
+ saved_val = radio->mute_mode.hard_mute;
radio->mute_mode.hard_mute = ctrl->value;
radio->mute_mode.soft_mute = IOC_SFT_MUTE;
retval = hci_set_fm_mute_mode(
&radio->mute_mode,
radio->fm_hdev);
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error while set FM hard mute"" %d\n",
- retval);
+ retval);
+ radio->mute_mode.hard_mute = saved_val;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_SRCHMODE:
- radio->g_search_mode = ctrl->value;
+ if (is_valid_srch_mode(ctrl->value)) {
+ radio->g_search_mode = ctrl->value;
+ } else {
+ FMDERR("%s: srch mode is not valid\n", __func__);
+ retval = -EINVAL;
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_SCANDWELL:
- radio->g_scan_time = ctrl->value;
+ if (is_valid_scan_dwell_prd(ctrl->value)) {
+ radio->g_scan_time = ctrl->value;
+ } else {
+ FMDERR("%s: scandwell period is not valid\n", __func__);
+ retval = -EINVAL;
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_SRCHON:
iris_search(radio, ctrl->value, SRCH_DIR_UP);
@@ -3636,8 +3762,12 @@
case V4L2_CID_PRIVATE_IRIS_STATE:
switch (ctrl->value) {
case FM_RECV:
- if (is_enable_rx_possible(radio) != 0)
- return -EINVAL;
+ if (is_enable_rx_possible(radio) != 0) {
+ FMDERR("%s: fm is not in proper state\n",
+ __func__);
+ retval = -EINVAL;
+ goto END;
+ }
radio->mode = FM_RECV_TURNING_ON;
retval = hci_cmd(HCI_FM_ENABLE_RECV_CMD,
radio->fm_hdev);
@@ -3645,14 +3775,16 @@
FMDERR("Error while enabling RECV FM"
" %d\n", retval);
radio->mode = FM_OFF;
- return retval;
+ goto END;
} else {
initialise_recv(radio);
}
break;
case FM_TRANS:
- if (is_enable_tx_possible(radio) != 0)
- return -EINVAL;
+ if (is_enable_tx_possible(radio) != 0) {
+ retval = -EINVAL;
+ goto END;
+ }
radio->mode = FM_TRANS_TURNING_ON;
retval = hci_cmd(HCI_FM_ENABLE_TRANS_CMD,
radio->fm_hdev);
@@ -3660,7 +3792,7 @@
FMDERR("Error while enabling TRANS FM"
" %d\n", retval);
radio->mode = FM_OFF;
- return retval;
+ goto END;
} else {
initialise_trans(radio);
}
@@ -3676,7 +3808,7 @@
FMDERR("Err on disable recv FM"
" %d\n", retval);
radio->mode = FM_RECV;
- return retval;
+ goto END;
}
break;
case FM_TRANS:
@@ -3688,7 +3820,7 @@
FMDERR("Err disabling trans FM"
" %d\n", retval);
radio->mode = FM_TRANS;
- return retval;
+ goto END;
}
break;
default:
@@ -3703,136 +3835,236 @@
if (radio->mode == FM_RECV) {
retval = iris_recv_set_region(radio, ctrl->value);
} else {
- if (radio->mode == FM_TRANS)
+ if (radio->mode == FM_TRANS) {
retval = iris_trans_set_region(radio,
ctrl->value);
- else
+ } else {
+ FMDERR("%s: fm is not in proper state\n",
+ __func__);
retval = -EINVAL;
+ goto END;
+ }
}
break;
case V4L2_CID_PRIVATE_IRIS_SIGNAL_TH:
+ if (!is_valid_sig_th(ctrl->value)) {
+ retval = -EINVAL;
+ FMDERR("%s: sig threshold is not valid\n", __func__);
+ goto END;
+ }
temp_val = ctrl->value;
retval = hci_fm_set_signal_threshold(
&temp_val,
radio->fm_hdev);
if (retval < 0) {
FMDERR("Error while setting signal threshold\n");
- break;
+ goto END;
}
break;
case V4L2_CID_PRIVATE_IRIS_SRCH_PTY:
- radio->srch_rds.srch_pty = ctrl->value;
- radio->srch_st_list.srch_pty = ctrl->value;
+ if (is_valid_pty(ctrl->value)) {
+ radio->srch_rds.srch_pty = ctrl->value;
+ radio->srch_st_list.srch_pty = ctrl->value;
+ } else {
+ FMDERR("%s: pty is not valid\n", __func__);
+ retval = -EINVAL;
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_SRCH_PI:
- radio->srch_rds.srch_pi = ctrl->value;
+ if (is_valid_pi(ctrl->value)) {
+ radio->srch_rds.srch_pi = ctrl->value;
+ } else {
+ retval = -EINVAL;
+ FMDERR("%s: Pi is not valid\n", __func__);
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_SRCH_CNT:
- radio->srch_st_list.srch_list_max = ctrl->value;
+ if (is_valid_srch_station_cnt(ctrl->value)) {
+ radio->srch_st_list.srch_list_max = ctrl->value;
+ } else {
+ retval = -EINVAL;
+ FMDERR("%s: srch station count is not valid\n",
+ __func__);
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_SPACING:
+ if (!is_valid_chan_spacing(ctrl->value)) {
+ retval = -EINVAL;
+ FMDERR("%s: channel spacing is not valid\n", __func__);
+ goto END;
+ }
if (radio->mode == FM_RECV) {
+ saved_val = radio->recv_conf.ch_spacing;
radio->recv_conf.ch_spacing = ctrl->value;
retval = hci_set_fm_recv_conf(
&radio->recv_conf,
radio->fm_hdev);
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error in setting channel spacing");
+ radio->recv_conf.ch_spacing = saved_val;
+ goto END;
+ }
}
break;
case V4L2_CID_PRIVATE_IRIS_EMPHASIS:
+ if (!is_valid_emphasis(ctrl->value)) {
+ retval = -EINVAL;
+ FMDERR("%s, emphasis is not valid\n", __func__);
+ goto END;
+ }
switch (radio->mode) {
case FM_RECV:
+ saved_val = radio->recv_conf.emphasis;
radio->recv_conf.emphasis = ctrl->value;
retval = hci_set_fm_recv_conf(
&radio->recv_conf,
radio->fm_hdev);
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error in setting emphasis");
+ radio->recv_conf.emphasis = saved_val;
+ goto END;
+ }
break;
case FM_TRANS:
+ saved_val = radio->trans_conf.emphasis;
radio->trans_conf.emphasis = ctrl->value;
retval = hci_set_fm_trans_conf(
&radio->trans_conf,
radio->fm_hdev);
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error in setting emphasis");
+ radio->trans_conf.emphasis = saved_val;
+ goto END;
+ }
break;
default:
retval = -EINVAL;
+ FMDERR("%s, FM is not in proper state\n", __func__);
+ goto END;
+ break;
}
break;
case V4L2_CID_PRIVATE_IRIS_RDS_STD:
+ if (!is_valid_rds_std(ctrl->value)) {
+ retval = -EINVAL;
+ FMDERR("%s: rds std is not valid\n", __func__);
+ goto END;
+ }
switch (radio->mode) {
case FM_RECV:
+ saved_val = radio->recv_conf.rds_std;
radio->recv_conf.rds_std = ctrl->value;
retval = hci_set_fm_recv_conf(
&radio->recv_conf,
radio->fm_hdev);
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error in rds_std");
+ radio->recv_conf.rds_std = saved_val;
+ goto END;
+ }
break;
case FM_TRANS:
+ saved_val = radio->trans_conf.rds_std;
radio->trans_conf.rds_std = ctrl->value;
retval = hci_set_fm_trans_conf(
&radio->trans_conf,
radio->fm_hdev);
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error in rds_Std");
+ radio->trans_conf.rds_std = saved_val;
+ goto END;
+ }
break;
default:
retval = -EINVAL;
+ FMDERR("%s: fm is not in proper state\n", __func__);
+ goto END;
+ break;
}
break;
case V4L2_CID_PRIVATE_IRIS_RDSON:
+ if (!is_valid_rds_std(ctrl->value)) {
+ retval = -EINVAL;
+ FMDERR("%s: rds std is not valid\n", __func__);
+ goto END;
+ }
switch (radio->mode) {
case FM_RECV:
+ saved_val = radio->recv_conf.rds_std;
radio->recv_conf.rds_std = ctrl->value;
retval = hci_set_fm_recv_conf(
&radio->recv_conf,
radio->fm_hdev);
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error in rds_std");
+ radio->recv_conf.rds_std = saved_val;
+ goto END;
+ }
break;
case FM_TRANS:
+ saved_val = radio->trans_conf.rds_std;
radio->trans_conf.rds_std = ctrl->value;
retval = hci_set_fm_trans_conf(
&radio->trans_conf,
radio->fm_hdev);
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error in rds_Std");
+ radio->trans_conf.rds_std = saved_val;
+ goto END;
+ }
break;
default:
retval = -EINVAL;
+ FMDERR("%s: fm is not in proper state\n", __func__);
+ goto END;
+ break;
}
break;
case V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK:
+ saved_val = radio->rds_grp.rds_grp_enable_mask;
grp_mask = (grp_mask | oda_agt | ctrl->value);
radio->rds_grp.rds_grp_enable_mask = grp_mask;
radio->rds_grp.rds_buf_size = 1;
radio->rds_grp.en_rds_change_filter = 0;
retval = hci_fm_rds_grp(&radio->rds_grp, radio->fm_hdev);
- if (retval < 0)
+ if (retval < 0) {
FMDERR("error in setting group mask\n");
+ radio->rds_grp.rds_grp_enable_mask = saved_val;
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_RDSGROUP_PROC:
+ saved_val = radio->g_rds_grp_proc_ps;
rds_grps_proc = radio->g_rds_grp_proc_ps | ctrl->value;
radio->g_rds_grp_proc_ps = (rds_grps_proc >> RDS_CONFIG_OFFSET);
retval = hci_fm_rds_grps_process(
&radio->g_rds_grp_proc_ps,
radio->fm_hdev);
+ if (retval < 0) {
+ radio->g_rds_grp_proc_ps = saved_val;
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_RDSD_BUF:
radio->rds_grp.rds_buf_size = ctrl->value;
break;
case V4L2_CID_PRIVATE_IRIS_PSALL:
+ saved_val = radio->g_rds_grp_proc_ps;
rds_grps_proc = (ctrl->value << RDS_CONFIG_OFFSET);
radio->g_rds_grp_proc_ps |= rds_grps_proc;
retval = hci_fm_rds_grps_process(
&radio->g_rds_grp_proc_ps,
radio->fm_hdev);
+ if (retval < 0) {
+ radio->g_rds_grp_proc_ps = saved_val;
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_AF_JUMP:
+ saved_val = radio->g_rds_grp_proc_ps;
/*Clear the current AF jump settings*/
radio->g_rds_grp_proc_ps &= ~(1 << RDS_AF_JUMP_OFFSET);
radio->af_jump_bit = ctrl->value;
@@ -3842,24 +4074,45 @@
retval = hci_fm_rds_grps_process(
&radio->g_rds_grp_proc_ps,
radio->fm_hdev);
+ if (retval < 0) {
+ radio->g_rds_grp_proc_ps = saved_val;
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_LP_MODE:
set_low_power_mode(radio, ctrl->value);
break;
case V4L2_CID_PRIVATE_IRIS_ANTENNA:
+ if (!is_valid_antenna(ctrl->value)) {
+ retval = -EINVAL;
+ FMDERR("%s: antenna type is not valid\n", __func__);
+ goto END;
+ }
temp_val = ctrl->value;
retval = hci_fm_set_antenna(&temp_val, radio->fm_hdev);
if (retval < 0) {
FMDERR("Set Antenna failed retval = %x", retval);
- return retval;
+ goto END;
}
radio->g_antenna = ctrl->value;
break;
case V4L2_CID_RDS_TX_PTY:
- radio->pty = ctrl->value;
+ if (is_valid_pty(ctrl->value)) {
+ radio->pty = ctrl->value;
+ } else {
+ retval = -EINVAL;
+ FMDERR("%s: pty is not valid\n", __func__);
+ goto END;
+ }
break;
case V4L2_CID_RDS_TX_PI:
- radio->pi = ctrl->value;
+ if (is_valid_pi(ctrl->value)) {
+ radio->pi = ctrl->value;
+ } else {
+ retval = -EINVAL;
+ FMDERR("%s: pi is not valid\n", __func__);
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_PS_NAME:
tx_ps.ps_control = 0x00;
@@ -3872,7 +4125,13 @@
(unsigned long)&tx_rt, RADIO_HCI_TIMEOUT);
break;
case V4L2_CID_PRIVATE_IRIS_TX_SETPSREPEATCOUNT:
- radio->ps_repeatcount = ctrl->value;
+ if (is_valid_ps_repeat_cnt(ctrl->value)) {
+ radio->ps_repeatcount = ctrl->value;
+ } else {
+ retval = -EINVAL;
+ FMDERR("%s: ps repeat count is not valid\n", __func__);
+ goto END;
+ }
break;
case V4L2_CID_TUNE_POWER_LEVEL:
if (ctrl->value > FM_TX_PWR_LVL_MAX)
@@ -3887,8 +4146,8 @@
retval = hci_def_data_read(&rd, radio->fm_hdev);
if (retval < 0) {
FMDERR("Default data read failed for PHY_CFG %d\n",
- retval);
- break;
+ retval);
+ goto END;
}
memset(&wrd, 0, sizeof(wrd));
wrd.mode = FM_TX_PHY_CFG_MODE;
@@ -3900,48 +4159,58 @@
retval = hci_def_data_write(&wrd, radio->fm_hdev);
if (retval < 0)
FMDERR("Default write failed for PHY_TXGAIN %d\n",
- retval);
+ retval);
break;
case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
+ if (!is_valid_soft_mute(ctrl->value)) {
+ retval = -EINVAL;
+ FMDERR("%s: soft mute is not valid\n", __func__);
+ goto END;
+ }
+ saved_val = radio->mute_mode.soft_mute;
radio->mute_mode.soft_mute = ctrl->value;
retval = hci_set_fm_mute_mode(
&radio->mute_mode,
radio->fm_hdev);
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error while setting FM soft mute"" %d\n",
- retval);
+ retval);
+ radio->mute_mode.soft_mute = saved_val;
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_ADDR:
radio->riva_data_req.cmd_params.start_addr = ctrl->value;
break;
case V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN:
- if ((ctrl->value > 0) &&
- (ctrl->value <= MAX_RIVA_PEEK_RSP_SIZE)) {
+ if (is_valid_peek_len(ctrl->value)) {
radio->riva_data_req.cmd_params.length = ctrl->value;
} else {
- FMDERR("Length %d is more than the buffer size %d\n",
- ctrl->value, MAX_RIVA_PEEK_RSP_SIZE);
retval = -EINVAL;
+ FMDERR("%s: riva access len is not valid\n", __func__);
+ goto END;
}
break;
case V4L2_CID_PRIVATE_IRIS_RIVA_POKE:
- if (radio->riva_data_req.cmd_params.length <= MAX_RIVA_PEEK_RSP_SIZE) {
- retval = copy_from_user(radio->riva_data_req.data,
- (void *)ctrl->value,
- radio->riva_data_req.cmd_params.length);
- if (retval == 0) {
- radio->riva_data_req.cmd_params.subopcode =
- RIVA_POKE_OPCODE;
- retval = hci_poke_data(&radio->riva_data_req,
- radio->fm_hdev);
- } else {
- retval = -EINVAL;
+ if (radio->riva_data_req.cmd_params.length <=
+ MAX_RIVA_PEEK_RSP_SIZE) {
+ retval = copy_from_user(
+ radio->riva_data_req.data,
+ (void *)ctrl->value,
+ radio->riva_data_req.cmd_params.length);
+ if (retval != 0) {
+ retval = -retval;
+ goto END;
}
+ radio->riva_data_req.cmd_params.subopcode =
+ RIVA_POKE_OPCODE;
+ retval = hci_poke_data(
+ &radio->riva_data_req,
+ radio->fm_hdev);
} else {
- FMDERR("Can not copy into driver's buffer. Length %d is more than"
- "the buffer size %d\n", radio->riva_data_req.cmd_params.length,
- MAX_RIVA_PEEK_RSP_SIZE);
+ FMDERR("Can not copy into driver's buffer.\n");
retval = -EINVAL;
+ goto END;
}
break;
case V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR:
@@ -3962,80 +4231,133 @@
hci_ssbi_peek_reg(&radio->ssbi_peek_reg, radio->fm_hdev);
break;
case V4L2_CID_PRIVATE_IRIS_RDS_GRP_COUNTERS:
- temp_val = ctrl->value;
- hci_read_grp_counters(&temp_val, radio->fm_hdev);
+ if (is_valid_reset_cntr(ctrl->value)) {
+ temp_val = ctrl->value;
+ hci_read_grp_counters(&temp_val, radio->fm_hdev);
+ } else {
+ FMDERR("%s: reset counter value is not valid\n",
+ __func__);
+ retval = -EINVAL;
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_IRIS_HLSI:
+ if (!is_valid_hlsi(ctrl->value)) {
+ FMDERR("%s: hlsi value is not valid\n", __func__);
+ retval = -EINVAL;
+ goto END;
+ }
retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
radio->fm_hdev);
if (retval)
- break;
+ goto END;
+ saved_val = radio->recv_conf.hlsi;
radio->recv_conf.hlsi = ctrl->value;
retval = hci_set_fm_recv_conf(
&radio->recv_conf,
radio->fm_hdev);
+ if (retval < 0)
+ radio->recv_conf.hlsi = saved_val;
break;
case V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER:
- temp_val = ctrl->value;
- retval = hci_set_notch_filter(&temp_val, radio->fm_hdev);
+ if (is_valid_notch_filter(ctrl->value)) {
+ temp_val = ctrl->value;
+ retval = hci_set_notch_filter(&temp_val,
+ radio->fm_hdev);
+ } else {
+ FMDERR("%s: notch filter is not valid\n", __func__);
+ retval = -EINVAL;
+ goto END;
+ }
break;
case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
+ if (!is_valid_intf_det_hgh_th(ctrl->value)) {
+ FMDERR("%s: intf high threshold is not valid\n",
+ __func__);
+ retval = -EINVAL;
+ goto END;
+ }
retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
if (retval < 0) {
FMDERR("Failed to get chnl det thresholds %d", retval);
- return retval;
+ goto END;
}
+ saved_val = radio->ch_det_threshold.high_th;
radio->ch_det_threshold.high_th = ctrl->value;
retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
radio->fm_hdev);
if (retval < 0) {
FMDERR("Failed to set High det threshold %d ", retval);
- return retval;
+ radio->ch_det_threshold.high_th = saved_val;
+ goto END;
}
break;
case V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD:
+ if (!is_valid_intf_det_low_th(ctrl->value)) {
+ FMDERR("%s: intf det low threshold is not valid\n",
+ __func__);
+ retval = -EINVAL;
+ goto END;
+ }
retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
if (retval < 0) {
FMDERR("Failed to get chnl det thresholds %d", retval);
- return retval;
+ goto END;
}
+ saved_val = radio->ch_det_threshold.low_th;
radio->ch_det_threshold.low_th = ctrl->value;
retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
radio->fm_hdev);
if (retval < 0) {
FMDERR("Failed to Set Low det threshold %d", retval);
- return retval;
+ radio->ch_det_threshold.low_th = saved_val;
+ goto END;
}
break;
case V4L2_CID_PRIVATE_SINR_THRESHOLD:
+ if (!is_valid_sinr_th(ctrl->value)) {
+ FMDERR("%s: sinr threshold is not valid\n", __func__);
+ retval = -EINVAL;
+ goto END;
+ }
retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
if (retval < 0) {
FMDERR("Failed to get chnl det thresholds %d", retval);
- return retval;
+ goto END;
}
+ saved_val = radio->ch_det_threshold.sinr;
radio->ch_det_threshold.sinr = ctrl->value;
retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
radio->fm_hdev);
if (retval < 0) {
FMDERR("Failed to set SINR threshold %d", retval);
- return retval;
+ radio->ch_det_threshold.sinr = saved_val;
+ goto END;
}
break;
case V4L2_CID_PRIVATE_SINR_SAMPLES:
+ if (!is_valid_sinr_samples(ctrl->value)) {
+ FMDERR("%s: sinr samples count is not valid\n",
+ __func__);
+ retval = -EINVAL;
+ goto END;
+ }
retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
if (retval < 0) {
FMDERR("Failed to get chnl det thresholds %d", retval);
- return retval;
+ goto END;
}
+ saved_val = radio->ch_det_threshold.sinr_samples;
radio->ch_det_threshold.sinr_samples = ctrl->value;
retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
radio->fm_hdev);
if (retval < 0) {
FMDERR("Failed to set SINR samples %d", retval);
- return retval;
+ radio->ch_det_threshold.sinr_samples = saved_val;
+ goto END;
}
break;
@@ -4082,18 +4404,23 @@
if (retval < 0) {
FMDERR("%s: Failed to determine channel's validity\n",
__func__);
- return retval;
+ goto END;
} else {
sinr_th = radio->ch_det_threshold.sinr;
intf_det_low_th = radio->ch_det_threshold.low_th;
intf_det_high_th = radio->ch_det_threshold.high_th;
}
-
+ if (!is_valid_sinr_th(sinr_th) ||
+ !is_valid_intf_det_low_th(intf_det_low_th) ||
+ !is_valid_intf_det_hgh_th(intf_det_high_th)) {
+ retval = -EINVAL;
+ goto END;
+ }
retval = hci_cmd(HCI_FM_GET_STATION_PARAM_CMD, radio->fm_hdev);
if (retval < 0) {
FMDERR("%s: Failed to determine channel's validity\n",
__func__);
- return retval;
+ goto END;
} else
sinr = radio->fm_st_rsp.station_rsp.sinr;
@@ -4101,7 +4428,7 @@
if (retval < 0) {
FMDERR("%s: Failed to determine channel's validity\n",
__func__);
- return retval;
+ goto END;
} else
intf_det_out = radio->st_dbg_param.in_det_out;
@@ -4120,7 +4447,7 @@
retval = hci_def_data_read(&rd, radio->fm_hdev);
if (retval < 0) {
FMDERR("default data read failed %x", retval);
- return retval;
+ goto END;
}
wrd.mode = FM_RDS_CNFG_MODE;
wrd.length = FM_RDS_CNFG_LEN;
@@ -4141,7 +4468,7 @@
retval = hci_def_data_read(&rd, radio->fm_hdev);
if (retval < 0) {
FMDERR("default data read failed %x", retval);
- return retval;
+ goto END;
}
wrd.mode = FM_RDS_CNFG_MODE;
wrd.length = FM_RDS_CNFG_LEN;
@@ -4161,7 +4488,7 @@
retval = hci_def_data_read(&rd, radio->fm_hdev);
if (retval < 0) {
FMDERR("default data read failed %x", retval);
- return retval;
+ goto END;
}
wrd.mode = FM_RX_CONFG_MODE;
wrd.length = FM_RX_CNFG_LEN;
@@ -4181,7 +4508,7 @@
retval = hci_def_data_read(&rd, radio->fm_hdev);
if (retval < 0) {
FMDERR("default data read failed %x", retval);
- return retval;
+ goto END;
}
wrd.mode = FM_RX_CONFG_MODE;
wrd.length = FM_RX_CNFG_LEN;
@@ -4201,7 +4528,7 @@
retval = hci_def_data_read(&rd, radio->fm_hdev);
if (retval < 0) {
FMDERR("default data read failed %x", retval);
- return retval;
+ goto END;
}
wrd.mode = FM_RX_CONFG_MODE;
wrd.length = FM_RX_CNFG_LEN;
@@ -4221,7 +4548,7 @@
retval = hci_def_data_read(&rd, radio->fm_hdev);
if (retval < 0) {
FMDERR("default data read failed %x", retval);
- return retval;
+ goto END;
}
wrd.mode = FM_RX_CONFG_MODE;
wrd.length = FM_RX_CNFG_LEN;
@@ -4241,7 +4568,7 @@
retval = hci_def_data_read(&rd, radio->fm_hdev);
if (retval < 0) {
FMDERR("default data read failed %x", retval);
- return retval;
+ goto END;
}
wrd.mode = FM_RX_CONFG_MODE;
wrd.length = FM_RX_CNFG_LEN;
@@ -4264,7 +4591,7 @@
retval = hci_def_data_read(&rd, radio->fm_hdev);
if (retval < 0) {
FMDERR("default data read failed for PS0 %x", retval);
- return retval;
+ goto END;
}
wrd.mode = RDS_PS0_XFR_MODE;
wrd.length = RDS_PS0_LEN;
@@ -4278,7 +4605,13 @@
break;
default:
retval = -EINVAL;
+ break;
}
+
+END:
+ if (retval > 0)
+ retval = -EINVAL;
+
return retval;
}
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index d28a8c0..a69f3f1 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -32,6 +32,50 @@
#include <linux/mutex.h>
#include <linux/atomic.h>
#include "radio-iris-commands.h"
+const unsigned char MIN_TX_TONE_VAL = 0x00;
+const unsigned char MAX_TX_TONE_VAL = 0x07;
+const unsigned char MIN_HARD_MUTE_VAL = 0x00;
+const unsigned char MAX_HARD_MUTE_VAL = 0x03;
+const unsigned char MIN_SRCH_MODE = 0x00;
+const unsigned char MAX_SRCH_MODE = 0x01;
+const unsigned char MIN_SCAN_DWELL = 0x00;
+const unsigned char MAX_SCAN_DWELL = 0x0F;
+const unsigned char MIN_SIG_TH = 0x00;
+const unsigned char MAX_SIG_TH = 0x03;
+const unsigned char MIN_PTY = 0X00;
+const unsigned char MAX_PTY = 0x1F;
+const unsigned short MIN_PI = 0x0000;
+const unsigned short MAX_PI = 0xFFFF;
+const unsigned char MIN_SRCH_STATIONS_CNT = 0x00;
+const unsigned char MAX_SRCH_STATIONS_CNT = 0x14;
+const unsigned char MIN_CHAN_SPACING = 0x00;
+const unsigned char MAX_CHAN_SPACING = 0x02;
+const unsigned char MIN_EMPHASIS = 0x00;
+const unsigned char MAX_EMPHASIS = 0x01;
+const unsigned char MIN_RDS_STD = 0x00;
+const unsigned char MAX_RDS_STD = 0x02;
+const unsigned char MIN_ANTENNA_VAL = 0x00;
+const unsigned char MAX_ANTENNA_VAL = 0x01;
+const unsigned char MIN_TX_PS_REPEAT_CNT = 0x01;
+const unsigned char MAX_TX_PS_REPEAT_CNT = 0x0F;
+const unsigned char MIN_SOFT_MUTE = 0x00;
+const unsigned char MAX_SOFT_MUTE = 0x01;
+const unsigned char MIN_PEEK_ACCESS_LEN = 0x01;
+const unsigned char MAX_PEEK_ACCESS_LEN = 0xF9;
+const unsigned char MIN_RESET_CNTR = 0x00;
+const unsigned char MAX_RESET_CNTR = 0x01;
+const unsigned char MIN_HLSI = 0x00;
+const unsigned char MAX_HLSI = 0x02;
+const unsigned char MIN_NOTCH_FILTER = 0x00;
+const unsigned char MAX_NOTCH_FILTER = 0x02;
+const unsigned char MIN_INTF_DET_OUT_LW_TH = 0x00;
+const unsigned char MAX_INTF_DET_OUT_LW_TH = 0xFF;
+const unsigned char MIN_INTF_DET_OUT_HG_TH = 0x00;
+const unsigned char MAX_INTF_DET_OUT_HG_TH = 0xFF;
+const signed char MIN_SINR_TH = -128;
+const signed char MAX_SINR_TH = 127;
+const unsigned char MIN_SINR_SAMPLES = 0x01;
+const unsigned char MAX_SINR_SAMPLES = 0xFF;
/* ---- HCI Packet structures ---- */
#define RADIO_HCI_COMMAND_HDR_SIZE sizeof(struct radio_hci_command_hdr)
@@ -630,6 +674,7 @@
FM_TURNING_OFF,
FM_RECV_TURNING_ON,
FM_TRANS_TURNING_ON,
+ FM_MAX_NO_STATES,
};
enum emphasis_type {
@@ -828,4 +873,209 @@
int hci_fm_do_calibration(__u8 *arg, struct radio_hci_dev *hdev);
int hci_fm_do_calibration(__u8 *arg, struct radio_hci_dev *hdev);
+static inline int is_valid_tone(int tone)
+{
+ if ((tone >= MIN_TX_TONE_VAL) &&
+ (tone <= MAX_TX_TONE_VAL))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_hard_mute(int hard_mute)
+{
+ if ((hard_mute >= MIN_HARD_MUTE_VAL) &&
+ (hard_mute <= MAX_HARD_MUTE_VAL))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_srch_mode(int srch_mode)
+{
+ if ((srch_mode >= MIN_SRCH_MODE) &&
+ (srch_mode <= MAX_SRCH_MODE))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_scan_dwell_prd(int scan_dwell_prd)
+{
+ if ((scan_dwell_prd >= MIN_SCAN_DWELL) &&
+ (scan_dwell_prd <= MAX_SCAN_DWELL))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_sig_th(int sig_th)
+{
+ if ((sig_th >= MIN_SIG_TH) &&
+ (sig_th <= MAX_SIG_TH))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_pty(int pty)
+{
+ if ((pty >= MIN_PTY) &&
+ (pty <= MAX_PTY))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_pi(int pi)
+{
+ if ((pi >= MIN_PI) &&
+ (pi <= MAX_PI))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_srch_station_cnt(int cnt)
+{
+ if ((cnt >= MIN_SRCH_STATIONS_CNT) &&
+ (cnt <= MAX_SRCH_STATIONS_CNT))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_chan_spacing(int spacing)
+{
+ if ((spacing >= MIN_CHAN_SPACING) &&
+ (spacing <= MAX_CHAN_SPACING))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_emphasis(int emphasis)
+{
+ if ((emphasis >= MIN_EMPHASIS) &&
+ (emphasis <= MAX_EMPHASIS))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_rds_std(int rds_std)
+{
+ if ((rds_std >= MIN_RDS_STD) &&
+ (rds_std <= MAX_RDS_STD))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_antenna(int antenna_type)
+{
+ if ((antenna_type >= MIN_ANTENNA_VAL) &&
+ (antenna_type <= MAX_ANTENNA_VAL))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_ps_repeat_cnt(int cnt)
+{
+ if ((cnt >= MIN_TX_PS_REPEAT_CNT) &&
+ (cnt <= MAX_TX_PS_REPEAT_CNT))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_soft_mute(int soft_mute)
+{
+ if ((soft_mute >= MIN_SOFT_MUTE) &&
+ (soft_mute <= MAX_SOFT_MUTE))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_peek_len(int len)
+{
+ if ((len >= MIN_PEEK_ACCESS_LEN) &&
+ (len <= MAX_PEEK_ACCESS_LEN))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_reset_cntr(int cntr)
+{
+ if ((cntr >= MIN_RESET_CNTR) &&
+ (cntr <= MAX_RESET_CNTR))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_hlsi(int hlsi)
+{
+ if ((hlsi >= MIN_HLSI) &&
+ (hlsi <= MAX_HLSI))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_notch_filter(int filter)
+{
+ if ((filter >= MIN_NOTCH_FILTER) &&
+ (filter <= MAX_NOTCH_FILTER))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_intf_det_low_th(int th)
+{
+ if ((th >= MIN_INTF_DET_OUT_LW_TH) &&
+ (th <= MAX_INTF_DET_OUT_LW_TH))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_intf_det_hgh_th(int th)
+{
+ if ((th >= MIN_INTF_DET_OUT_HG_TH) &&
+ (th <= MAX_INTF_DET_OUT_HG_TH))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_sinr_th(int th)
+{
+ if ((th >= MIN_SINR_TH) &&
+ (th <= MAX_SINR_TH))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_sinr_samples(int samples_cnt)
+{
+ if ((samples_cnt >= MIN_SINR_SAMPLES) &&
+ (samples_cnt <= MAX_SINR_SAMPLES))
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_valid_fm_state(int state)
+{
+ if ((state >= 0) && (state < FM_MAX_NO_STATES))
+ return 1;
+ else
+ return 0;
+}
#endif /* __RADIO_HCI_CORE_H */