1264 lines
35 KiB
C++
Executable file
1264 lines
35 KiB
C++
Executable file
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/*******************************************************************
|
|
* FM JNI core
|
|
* return -1 if error occured. else return needed value.
|
|
* if return type is char *, return NULL if error occured.
|
|
* Do NOT return value access paramater.
|
|
*
|
|
* FM JNI core should be independent from lower layer, that means
|
|
* there should be no low layer dependent data struct in FM JNI core
|
|
*
|
|
* Naming rule: FMR_n(paramter Micro), FMR_v(functions), fmr_n(global param)
|
|
* pfmr_n(global paramter pointer)
|
|
*
|
|
*******************************************************************/
|
|
|
|
#include "fmr.h"
|
|
|
|
#ifdef LOG_TAG
|
|
#undef LOG_TAG
|
|
#endif
|
|
#define LOG_TAG "FMLIB_CORE"
|
|
|
|
#define FMR_MAX_IDX 1
|
|
|
|
struct fmr_ds fmr_data;
|
|
struct fmr_ds *pfmr_data[FMR_MAX_IDX] = {0};
|
|
#define FMR_fd(idx) ((pfmr_data[idx])->fd)
|
|
#define FMR_err(idx) ((pfmr_data[idx])->err)
|
|
#define FMR_chip(idx) ((pfmr_data[idx])->cfg_data.chip)
|
|
#define FMR_low_band(idx) ((pfmr_data[idx])->cfg_data.low_band)
|
|
#define FMR_high_band(idx) ((pfmr_data[idx])->cfg_data.high_band)
|
|
#define FMR_seek_space(idx) ((pfmr_data[idx])->cfg_data.seek_space)
|
|
#define FMR_max_scan_num(idx) ((pfmr_data[idx])->cfg_data.max_scan_num)
|
|
#define FMR_cbk_tbl(idx) ((pfmr_data[idx])->tbl)
|
|
#define FMR_cust_hdler(idx) ((pfmr_data[idx])->custom_handler)
|
|
#define FMR_get_cfg(idx) ((pfmr_data[idx])->get_cfg)
|
|
#define UNUSED(x) (void)(x)
|
|
|
|
int FMR_get_cfgs(int idx)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -ERR_INVALID_PARA;
|
|
}
|
|
|
|
CUST_get_cfg(&(pfmr_data[idx]->cfg_data));
|
|
LOGI("OK\n");
|
|
|
|
FMR_cust_hdler(idx) = NULL;
|
|
FMR_get_cfg(idx) = NULL;
|
|
|
|
LOGI("%s successfully. chip: 0x%x, lband: %d, hband: %d, seek_space: %d, max_scan_num: %d\n", __FUNCTION__, FMR_chip(idx), FMR_low_band(idx), FMR_high_band(idx), FMR_seek_space(idx), FMR_max_scan_num(idx));
|
|
|
|
return ret;
|
|
}
|
|
|
|
int FMR_chk_cfg_data(int idx)
|
|
{
|
|
//TODO Need check? how to check?
|
|
UNUSED(idx);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int FMR_init()
|
|
{
|
|
int idx;
|
|
int ret = 0;
|
|
//signal(4, sig_alarm);
|
|
|
|
for (idx=0; idx<FMR_MAX_IDX; idx++) {
|
|
if (pfmr_data[idx] == NULL) {
|
|
break;
|
|
}
|
|
}
|
|
LOGI("FMR idx = %d\n", idx);
|
|
if (idx == FMR_MAX_IDX) {
|
|
//FMR_seterr(ERR_NO_MORE_IDX);
|
|
return -1;
|
|
}
|
|
|
|
/*The best way here is to call malloc to alloc mem for each idx,but
|
|
I do not know where to release it, so use static global param instead*/
|
|
pfmr_data[idx] = &fmr_data;
|
|
memset(pfmr_data[idx], 0, sizeof(struct fmr_ds));
|
|
|
|
if (FMR_get_cfgs(idx) < 0) {
|
|
LOGI("FMR_get_cfgs failed\n");
|
|
goto fail;
|
|
}
|
|
|
|
if (FMR_chk_cfg_data(idx) < 0) {
|
|
LOGI("FMR_chk_cfg_data failed\n");
|
|
goto fail;
|
|
}
|
|
|
|
pfmr_data[idx]->init_func = FM_interface_init;
|
|
if (pfmr_data[idx]->init_func == NULL) {
|
|
LOGE("%s init_func error, %s\n", __func__, dlerror());
|
|
goto fail;
|
|
} else {
|
|
LOGI("Go to run init function\n");
|
|
(*pfmr_data[idx]->init_func)(&(pfmr_data[idx]->tbl));
|
|
LOGI("OK\n");
|
|
ret = 0;
|
|
}
|
|
|
|
return idx;
|
|
|
|
fail:
|
|
pfmr_data[idx] = NULL;
|
|
|
|
return -1;
|
|
}
|
|
|
|
int FMR_open_dev(int idx)
|
|
{
|
|
int ret = 0;
|
|
int real_chip = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).open_dev);
|
|
|
|
ret = FMR_cbk_tbl(idx).open_dev(FM_DEV_NAME, &FMR_fd(idx));
|
|
if (ret || FMR_fd(idx) < 0) {
|
|
LOGE("%s failed, [fd=%d]\n", __func__, FMR_fd(idx));
|
|
return ret;
|
|
}
|
|
|
|
//Check if customer's cfg matchs driver.
|
|
ret = FMR_get_chip_id(idx, &real_chip);
|
|
if (FMR_chip(idx) != real_chip) {
|
|
LOGE("%s, 0x%x != 0x%x, reinit cfg.\n", __func__, FMR_chip(idx), real_chip);
|
|
CUST_update_cfg(&(pfmr_data[idx]->cfg_data), real_chip);
|
|
}
|
|
if (FMR_chip(idx) != real_chip) {
|
|
LOGE("%s, Chip config error. 0x%x != 0x%x\n", __func__,
|
|
FMR_chip(idx), real_chip);
|
|
ret = FMR_cbk_tbl(idx).close_dev(FMR_fd(idx));
|
|
return ret;
|
|
}
|
|
|
|
LOGD("%s, [fd=%d] [chipid=0x%x] [ret=%d]\n", __func__, FMR_fd(idx), real_chip, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_close_dev(int idx)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).close_dev);
|
|
ret = FMR_cbk_tbl(idx).close_dev(FMR_fd(idx));
|
|
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, FMR_fd(idx), ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_pwr_up(int idx, int freq)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).pwr_up);
|
|
|
|
LOGI("%s,[freq=%d]\n", __func__, freq);
|
|
if (freq < fmr_data.cfg_data.low_band || freq > fmr_data.cfg_data.high_band) {
|
|
LOGE("%s error freq: %d\n", __func__, freq);
|
|
ret = -ERR_INVALID_PARA;
|
|
return ret;
|
|
}
|
|
ret = FMR_cbk_tbl(idx).pwr_up(FMR_fd(idx), fmr_data.cfg_data.band, freq);
|
|
if (ret) {
|
|
LOGE("%s failed, [ret=%d]\n", __func__, ret);
|
|
}
|
|
fmr_data.cur_freq = freq;
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_pwr_down(int idx, int type)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).pwr_down);
|
|
ret = FMR_cbk_tbl(idx).pwr_down(FMR_fd(idx), type);
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_chip_id(int idx, int *chipid)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_chip_id);
|
|
FMR_ASSERT(chipid);
|
|
|
|
ret = FMR_cbk_tbl(idx).get_chip_id(FMR_fd(idx), chipid);
|
|
if (ret) {
|
|
LOGE("%s failed, %s\n", __func__, FMR_strerr());
|
|
*chipid = -1;
|
|
}
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_rssi(int idx, int *rssi)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_rssi);
|
|
FMR_ASSERT(rssi);
|
|
|
|
ret = FMR_cbk_tbl(idx).get_rssi(FMR_fd(idx), rssi);
|
|
if (ret){
|
|
LOGE("%s failed, [ret=%d]\n", __func__, ret);
|
|
*rssi = -1;
|
|
}
|
|
LOGD("%s, [rssi=%d] [ret=%d]\n", __func__, *rssi, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_ps(int idx, uint8_t **ps, int *ps_len)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_ps);
|
|
FMR_ASSERT(ps);
|
|
FMR_ASSERT(ps_len);
|
|
ret = FMR_cbk_tbl(idx).get_ps(FMR_fd(idx), &fmr_data.rds, ps, ps_len);
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_rt(int idx, uint8_t **rt, int *rt_len)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_rt);
|
|
FMR_ASSERT(rt);
|
|
FMR_ASSERT(rt_len);
|
|
|
|
ret = FMR_cbk_tbl(idx).get_rt(FMR_fd(idx), &fmr_data.rds, rt, rt_len);
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_pi(int idx, uint16_t *pi)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_pi);
|
|
|
|
ret = FMR_cbk_tbl(idx).get_pi(FMR_fd(idx), &fmr_data.rds, pi);
|
|
if (ret){
|
|
LOGE("%s failed, %s\n", __func__, FMR_strerr());
|
|
*pi = 0;
|
|
}
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_ecc(int idx, uint8_t *ecc)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_ecc);
|
|
|
|
ret = FMR_cbk_tbl(idx).get_ecc(FMR_fd(idx), &fmr_data.rds, ecc);
|
|
if (ret){
|
|
LOGE("%s failed\n", __func__);
|
|
*ecc = -1;
|
|
}
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_pty(int idx, uint8_t *pty)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_pty);
|
|
|
|
ret = FMR_cbk_tbl(idx).get_pty(FMR_fd(idx), &fmr_data.rds, pty);
|
|
if (ret){
|
|
*pty = -1;
|
|
LOGI("%s failed, %s\n", __func__, FMR_strerr());
|
|
}
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_tune(int idx, int freq)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).tune);
|
|
|
|
ret = FMR_cbk_tbl(idx).tune(FMR_fd(idx), freq, fmr_data.cfg_data.band);
|
|
if (ret) {
|
|
LOGE("%s failed, [ret=%d]\n", __func__, ret);
|
|
}
|
|
fmr_data.cur_freq = freq;
|
|
LOGD("%s, [freq=%d] [ret=%d]\n", __func__, freq, ret);
|
|
return ret;
|
|
}
|
|
|
|
/*return: fm_true: desense, fm_false: not desene channel*/
|
|
fm_bool FMR_DensenseDetect(fm_s32 idx, fm_u16 ChannelNo, fm_s32 RSSI)
|
|
{
|
|
fm_u8 bDesenseCh = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return fm_false;
|
|
}
|
|
|
|
bDesenseCh = FMR_cbk_tbl(idx).desense_check(FMR_fd(idx), ChannelNo, RSSI);
|
|
if (bDesenseCh == 1) {
|
|
return fm_true;
|
|
}
|
|
return fm_false;
|
|
}
|
|
|
|
fm_bool FMR_SevereDensense(fm_u16 ChannelNo, fm_s32 RSSI)
|
|
{
|
|
fm_s32 i = 0;
|
|
struct fm_fake_channel_t *chan_info = fmr_data.cfg_data.fake_chan;
|
|
|
|
for (i=0; i<chan_info->size; i++) {
|
|
if (ChannelNo == chan_info->chan[i].freq) {
|
|
//if (RSSI < FM_SEVERE_RSSI_TH)
|
|
if (RSSI < chan_info->chan[i].rssi_th) {
|
|
LOGI(" SevereDensense[%d] RSSI[%d]\n", ChannelNo,RSSI);
|
|
return fm_true;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return fm_false;
|
|
}
|
|
#if (FMR_NOISE_FLOORT_DETECT==1)
|
|
/*return TRUE:get noise floor freq*/
|
|
fm_bool FMR_NoiseFloorDetect(fm_bool *rF, fm_s32 rssi, fm_s32 *F_rssi)
|
|
{
|
|
if (rF[0] == fm_true) {
|
|
if (rF[1] == fm_true) {
|
|
F_rssi[2] = rssi;
|
|
rF[2] = fm_true;
|
|
return fm_true;
|
|
} else {
|
|
F_rssi[1] = rssi;
|
|
rF[1] = fm_true;
|
|
}
|
|
} else {
|
|
F_rssi[0] = rssi;
|
|
rF[0] = fm_true;
|
|
}
|
|
return fm_false;
|
|
}
|
|
#endif
|
|
|
|
/*check the cur_freq->freq is valid or not
|
|
return fm_true : need check cur_freq->valid
|
|
fm_false: check faild, should stop seek
|
|
*/
|
|
static fm_bool FMR_Seek_TuneCheck(int idx, fm_softmute_tune_t *cur_freq)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return fm_false;
|
|
}
|
|
|
|
if (fmr_data.scan_stop == fm_true) {
|
|
ret = FMR_tune(idx,fmr_data.cur_freq);
|
|
LOGI("seek stop!!! tune ret=%d",ret);
|
|
return fm_false;
|
|
}
|
|
ret = FMR_cbk_tbl(idx).soft_mute_tune(FMR_fd(idx), cur_freq);
|
|
if (ret) {
|
|
LOGE("soft mute tune, failed:[%d]\n",ret);
|
|
cur_freq->valid = fm_false;
|
|
return fm_true;
|
|
}
|
|
if (cur_freq->valid == fm_true)/*get valid channel*/ {
|
|
if (FMR_DensenseDetect(idx, cur_freq->freq, cur_freq->rssi) == fm_true) {
|
|
LOGI("desense channel detected:[%d] \n", cur_freq->freq);
|
|
cur_freq->valid = fm_false;
|
|
return fm_true;
|
|
}
|
|
if (FMR_SevereDensense(cur_freq->freq, cur_freq->rssi) == fm_true) {
|
|
LOGI("sever desense channel detected:[%d] \n", cur_freq->freq);
|
|
cur_freq->valid = fm_false;
|
|
return fm_true;
|
|
}
|
|
LOGI("seek result freq:[%d] \n", cur_freq->freq);
|
|
}
|
|
return fm_true;
|
|
}
|
|
/*
|
|
check more 2 freq, curfreq: current freq, seek_dir: 1,forward. 0,backword
|
|
*/
|
|
static int FMR_Seek_More(int idx, fm_softmute_tune_t *validfreq, fm_u8 seek_dir, fm_u8 step, fm_u16 min_freq, fm_u16 max_freq)
|
|
{
|
|
fm_s32 i;
|
|
fm_softmute_tune_t cur_freq;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
cur_freq.freq = validfreq->freq;
|
|
cur_freq.rssi = 0;
|
|
|
|
for (i=0; i<2; i++) {
|
|
if (seek_dir)/*forward*/ {
|
|
if (cur_freq.freq + step > max_freq) {
|
|
return 0;
|
|
}
|
|
cur_freq.freq += step;
|
|
} else/*backward*/ {
|
|
if (cur_freq.freq - step < min_freq) {
|
|
return 0;
|
|
}
|
|
cur_freq.freq -= step;
|
|
}
|
|
if (FMR_Seek_TuneCheck(idx, &cur_freq) == fm_true) {
|
|
if (cur_freq.valid == fm_true) {
|
|
if (cur_freq.rssi > validfreq->rssi) {
|
|
validfreq->freq = cur_freq.freq;
|
|
validfreq->rssi = cur_freq.rssi;
|
|
LOGI("seek cover last by freq=%d",cur_freq.freq);
|
|
}
|
|
}
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*check the a valid channel
|
|
return -1 : seek fail
|
|
0: seek success
|
|
*/
|
|
int FMR_seek_Channel(int idx, int start_freq, int min_freq, int max_freq, int band_channel_no, int seek_space, int dir, int *ret_freq, int *rssi_tmp)
|
|
{
|
|
fm_s32 i, ret = 0;
|
|
fm_softmute_tune_t cur_freq;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
memset(&cur_freq, 0, sizeof(struct fm_softmute_tune_t));
|
|
|
|
if (dir == 1)/*forward*/ {
|
|
for (i=((start_freq-min_freq)/seek_space+1); i<band_channel_no; i++) {
|
|
cur_freq.freq = min_freq + seek_space*i;
|
|
LOGI("i=%d, freq=%d-----1",i,cur_freq.freq);
|
|
ret = FMR_Seek_TuneCheck(idx, &cur_freq);
|
|
if (ret == fm_false) {
|
|
return -1;
|
|
} else {
|
|
if (cur_freq.valid == fm_false) {
|
|
continue;
|
|
} else {
|
|
if ((seek_space == 5) && (start_freq == cur_freq.freq - seek_space)) {
|
|
continue; // filter the same channel
|
|
}
|
|
if (FMR_Seek_More(idx, &cur_freq, dir, seek_space, min_freq, max_freq) == 0) {
|
|
*ret_freq = cur_freq.freq;
|
|
*rssi_tmp = cur_freq.rssi;
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (i=0; i<((start_freq-min_freq)/seek_space); i++) {
|
|
cur_freq.freq = min_freq + seek_space*i;
|
|
LOGI("i=%d, freq=%d-----2",i,cur_freq.freq);
|
|
ret = FMR_Seek_TuneCheck(idx, &cur_freq);
|
|
if (ret == fm_false) {
|
|
return -1;
|
|
} else {
|
|
if (cur_freq.valid == fm_false) {
|
|
continue;
|
|
} else {
|
|
if ((seek_space == 5) && (start_freq == cur_freq.freq - seek_space)) {
|
|
continue; // filter the same channel
|
|
}
|
|
if (FMR_Seek_More(idx, &cur_freq, dir, seek_space, min_freq, max_freq) == 0) {
|
|
*ret_freq = cur_freq.freq;
|
|
*rssi_tmp = cur_freq.rssi;
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else/*backward*/ {
|
|
for (i=((start_freq-min_freq)/seek_space-1); i>=0; i--) {
|
|
cur_freq.freq = min_freq + seek_space*i;
|
|
LOGI("i=%d, freq=%d-----3",i,cur_freq.freq);
|
|
ret = FMR_Seek_TuneCheck(idx, &cur_freq);
|
|
if (ret == fm_false) {
|
|
return -1;
|
|
} else {
|
|
if (cur_freq.valid == fm_false) {
|
|
continue;
|
|
} else {
|
|
if ((seek_space == 5) && (start_freq == cur_freq.freq + seek_space)) {
|
|
continue; // filter the same channel
|
|
}
|
|
if (FMR_Seek_More(idx, &cur_freq, dir, seek_space, min_freq, max_freq) == 0) {
|
|
*ret_freq = cur_freq.freq;
|
|
*rssi_tmp = cur_freq.rssi;
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (i=(band_channel_no-1); i>((start_freq-min_freq)/seek_space); i--) {
|
|
cur_freq.freq = min_freq + seek_space*i;
|
|
LOGI("i=%d, freq=%d-----4",i,cur_freq.freq);
|
|
ret = FMR_Seek_TuneCheck(idx, &cur_freq);
|
|
if (ret == fm_false) {
|
|
return -1;
|
|
} else {
|
|
if (cur_freq.valid == fm_false) {
|
|
continue;
|
|
} else {
|
|
if ((seek_space == 5) && (start_freq == cur_freq.freq + seek_space)) {
|
|
continue; // filter the same channel
|
|
}
|
|
if (FMR_Seek_More(idx, &cur_freq, dir,seek_space, min_freq, max_freq) == 0) {
|
|
*ret_freq = cur_freq.freq;
|
|
*rssi_tmp = cur_freq.rssi;
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
*ret_freq = start_freq;
|
|
return 0;
|
|
}
|
|
|
|
int FMR_seek(int idx, int start_freq, int dir, int *ret_freq)
|
|
{
|
|
fm_s32 ret = 0;
|
|
fm_s32 band_channel_no = 0;
|
|
fm_u8 seek_space = 10;
|
|
fm_u16 min_freq, max_freq;
|
|
int rssi;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
if ((start_freq < 7600) || (start_freq > 10800)) /*need replace by macro*/ {
|
|
LOGE("%s error start_freq: %d\n", __func__, start_freq);
|
|
return -ERR_INVALID_PARA;
|
|
}
|
|
|
|
//FM radio seek space,5:50KHZ; 1:100KHZ; 2:200KHZ
|
|
if (fmr_data.cfg_data.seek_space == 5) {
|
|
seek_space = 5;
|
|
} else if (fmr_data.cfg_data.seek_space == 2) {
|
|
seek_space = 20;
|
|
} else {
|
|
seek_space = 10;
|
|
}
|
|
if (fmr_data.cfg_data.band == FM_BAND_JAPAN)/* Japan band 76MHz ~ 90MHz */ {
|
|
band_channel_no = (9600-7600)/seek_space + 1;
|
|
min_freq = 7600;
|
|
max_freq = 9600;
|
|
} else if (fmr_data.cfg_data.band == FM_BAND_JAPANW)/* Japan wideband 76MHz ~ 108MHz */ {
|
|
band_channel_no = (10800-7600)/seek_space + 1;
|
|
min_freq = 7600;
|
|
max_freq = 10800;
|
|
} else/* US/Europe band 87.5MHz ~ 108MHz (DEFAULT) */ {
|
|
band_channel_no = (10800-8750)/seek_space + 1;
|
|
min_freq = 8750;
|
|
max_freq = 10800;
|
|
}
|
|
|
|
fmr_data.scan_stop = fm_false;
|
|
LOGD("seek start freq %d band_channel_no=[%d], seek_space=%d band[%d - %d] dir=%d\n", start_freq, band_channel_no,seek_space,min_freq,max_freq,dir);
|
|
|
|
ret = FMR_seek_Channel(idx, start_freq, min_freq, max_freq, band_channel_no, seek_space, dir, ret_freq, &rssi);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int FMR_set_mute(int idx, int mute)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).set_mute)
|
|
|
|
if ((mute < 0) || (mute > 1)) {
|
|
LOGE("%s error param mute: %d\n", __func__, mute);
|
|
}
|
|
|
|
ret = FMR_cbk_tbl(idx).set_mute(FMR_fd(idx), mute);
|
|
if (ret) {
|
|
LOGE("%s failed, %s\n", __func__, FMR_strerr());
|
|
}
|
|
LOGD("%s, [mute=%d] [ret=%d]\n", __func__, mute, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_is_fm_pwrup(int idx, int *pwrup)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).is_fm_pwrup);
|
|
FMR_ASSERT(pwrup);
|
|
|
|
ret = FMR_cbk_tbl(idx).is_fm_pwrup(FMR_fd(idx), pwrup);
|
|
if (ret){
|
|
*pwrup = 0;
|
|
LOGE("%s failed, %s\n", __func__, FMR_strerr());
|
|
}
|
|
|
|
LOGD("%s, [pwrup=%d] [ret=%d]\n", __func__, *pwrup, ret);
|
|
return ret;
|
|
}
|
|
int FMR_is_rdsrx_support(int idx, int *supt)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).is_rdsrx_support);
|
|
FMR_ASSERT(supt);
|
|
|
|
ret = FMR_cbk_tbl(idx).is_rdsrx_support(FMR_fd(idx), supt);
|
|
if (ret) {
|
|
*supt = 0;
|
|
LOGE("%s, failed\n", __func__);
|
|
}
|
|
LOGD("%s, [supt=%d] [ret=%d]\n", __func__, *supt, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_Pre_Search(int idx)
|
|
{
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
//avoid scan stop flag clear if stop cmd send before pre-search finish
|
|
fmr_data.scan_stop = fm_false;
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).pre_search);
|
|
FMR_cbk_tbl(idx).pre_search(FMR_fd(idx));
|
|
return 0;
|
|
}
|
|
|
|
int FMR_Restore_Search(int idx)
|
|
{
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).restore_search);
|
|
FMR_cbk_tbl(idx).restore_search(FMR_fd(idx));
|
|
return 0;
|
|
}
|
|
|
|
int FMR_scan_Channels(int idx, uint16_t *scan_tbl, int *max_cnt, fm_s32 band_channel_no, fm_u16 Start_Freq, fm_u8 seek_space, fm_u8 NF_Space)
|
|
{
|
|
fm_s32 ret = 0, Num = 0, i, j;
|
|
fm_u32 ChannelNo = 0;
|
|
fm_softmute_tune_t cur_freq;
|
|
static struct fm_cqi SortData[CQI_CH_NUM_MAX];
|
|
fm_bool LastExist = fm_false;
|
|
struct fm_cqi swap;
|
|
#if (FMR_NOISE_FLOORT_DETECT==1)
|
|
fm_s32 Pacc = 0, Nacc = 0;
|
|
fm_s32 NF = 0;
|
|
fm_bool F[3] = {fm_false, fm_false, fm_false};
|
|
fm_s32 F_Rssi[3] = {0};
|
|
#endif
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
memset(SortData, 0, CQI_CH_NUM_MAX*sizeof(struct fm_cqi));
|
|
LOGI("band_channel_no=[%d], seek_space=%d, start freq=%d, NF_Space=%d\n", band_channel_no,seek_space,Start_Freq, NF_Space);
|
|
for (i=0; i<band_channel_no; i++) {
|
|
if (fmr_data.scan_stop == fm_true) {
|
|
FMR_Restore_Search(idx);
|
|
ret = FMR_tune(idx, fmr_data.cur_freq);
|
|
LOGI("scan stop!!! tune ret=%d",ret);
|
|
return -1;
|
|
}
|
|
cur_freq.freq = Start_Freq + seek_space*i;
|
|
ret = FMR_cbk_tbl(idx).soft_mute_tune(FMR_fd(idx), &cur_freq);
|
|
if (ret) {
|
|
LOGE("soft mute tune, failed:[%d]\n",ret);
|
|
LastExist = fm_false;
|
|
continue;
|
|
}
|
|
if (cur_freq.valid == fm_true)/*get valid channel*/ {
|
|
#if (FMR_NOISE_FLOORT_DETECT==1)
|
|
memset(F, fm_false, sizeof(F));
|
|
#endif
|
|
if (FMR_DensenseDetect(idx, cur_freq.freq, cur_freq.rssi) == fm_true) {
|
|
LOGI("desense channel detected:[%d] \n", cur_freq.freq);
|
|
LastExist = fm_false;
|
|
continue;
|
|
}
|
|
if ((LastExist == fm_true) && (Num > 0)) /*neighbor channel*/ {
|
|
if (cur_freq.rssi>SortData[Num-1].rssi)/*save current freq and cover last channel*/ {
|
|
if (FMR_SevereDensense(cur_freq.freq, cur_freq.rssi) == fm_true) {
|
|
LastExist = fm_false;
|
|
continue;
|
|
}
|
|
SortData[Num-1].ch=cur_freq.freq;
|
|
SortData[Num-1].rssi=cur_freq.rssi;
|
|
SortData[Num-1].reserve = 1;
|
|
LOGI("cover last channel \n");
|
|
} else/*ignore current freq*/ {
|
|
LastExist = fm_false;
|
|
continue;
|
|
}
|
|
} else/*save current*/ {
|
|
if (FMR_SevereDensense(cur_freq.freq, cur_freq.rssi) == fm_true) {
|
|
LastExist = fm_false;
|
|
continue;
|
|
}
|
|
if (Num < 0 || Num >= CQI_CH_NUM_MAX) {
|
|
continue;
|
|
}
|
|
SortData[Num].ch = cur_freq.freq;
|
|
SortData[Num].rssi = cur_freq.rssi;
|
|
SortData[Num].reserve = 1;
|
|
Num++;
|
|
LastExist = fm_true;
|
|
LOGI("Num++:[%d] \n", Num);
|
|
}
|
|
} else {
|
|
#if (FMR_NOISE_FLOORT_DETECT==1)
|
|
if (FMR_DensenseDetect(idx, cur_freq.freq, cur_freq.rssi) == fm_false) {
|
|
if (FMR_NoiseFloorDetect(F, cur_freq.rssi, F_Rssi) == fm_true) {
|
|
Pacc += F_Rssi[1];
|
|
Nacc++;
|
|
/*check next freq*/
|
|
F[0] = F[1];
|
|
F_Rssi[0] = F_Rssi[1];
|
|
F[1] = F[2];
|
|
F_Rssi[1] = F_Rssi[2];
|
|
F[2] = fm_false;
|
|
F_Rssi[2] = 0;
|
|
LOGI("FM Noise FLoor:Pacc=[%d] Nacc=[%d] \n", Pacc,Nacc);
|
|
}
|
|
} else {
|
|
memset(F, fm_false, sizeof(F));
|
|
}
|
|
#endif
|
|
LastExist = fm_false;
|
|
}
|
|
#if (FMR_NOISE_FLOORT_DETECT==1)
|
|
if (((i%NF_Space) == 0) && (i != 0)) {
|
|
if (Nacc > 0) {
|
|
NF = Pacc/Nacc;
|
|
} else {
|
|
NF = RSSI_TH-FM_NOISE_FLOOR_OFFSET;
|
|
}
|
|
Pacc = 0;
|
|
Nacc = 0;
|
|
for (j = 0; j < Num; j++) {
|
|
if (SortData[j].rssi < (NF + FM_NOISE_FLOOR_OFFSET)) {
|
|
LOGI("FM Noise FLoor Detected:freq=[%d] NF=[%d] \n", SortData[j].ch, NF);
|
|
SortData[j].reserve = 0;
|
|
}
|
|
}
|
|
LOGI("FM Noise FLoor NF_Idx[%d] \n", j);
|
|
}
|
|
#endif
|
|
}
|
|
LOGI("get channel no.[%d] \n", Num);
|
|
if (Num == 0)/*get nothing*/ {
|
|
*max_cnt = 0;
|
|
FMR_Restore_Search(idx);
|
|
return -1;
|
|
}
|
|
|
|
switch (fmr_data.cfg_data.scan_sort)
|
|
{
|
|
case FM_SCAN_SORT_UP:
|
|
case FM_SCAN_SORT_DOWN:
|
|
{
|
|
LOGI("Start sort \n");
|
|
//do sort: insert sort algorithm
|
|
for (i = 1; i < Num; i++) {
|
|
for (j = i; (j > 0) && ((FM_SCAN_SORT_DOWN == fmr_data.cfg_data.scan_sort) ? (SortData[j-1].rssi \
|
|
< SortData[j].rssi) : (SortData[j-1].rssi > SortData[j].rssi)); j--) {
|
|
memcpy(&swap, &SortData[j], sizeof(struct fm_cqi));
|
|
memcpy(&SortData[j], &SortData[j-1], sizeof(struct fm_cqi));
|
|
memcpy(&SortData[j-1], &swap, sizeof(struct fm_cqi));
|
|
}
|
|
}
|
|
LOGI("End sort \n");
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
ChannelNo = 0;
|
|
for (i=0; i<Num; i++) {
|
|
if (SortData[i].reserve == 1) {
|
|
if (10 == seek_space)
|
|
SortData[i].ch /= 10;
|
|
|
|
scan_tbl[ChannelNo] = SortData[i].ch;
|
|
LOGI("scan_tbl[%d]:%d\n", i, scan_tbl[ChannelNo]);
|
|
ChannelNo++;
|
|
}
|
|
}
|
|
*max_cnt=ChannelNo;
|
|
|
|
LOGI("return channel no.[%d] \n", ChannelNo);
|
|
return 0;
|
|
}
|
|
|
|
int FMR_scan(int idx, uint16_t *scan_tbl, int *max_cnt)
|
|
{
|
|
fm_s32 ret = 0;
|
|
fm_s32 band_channel_no = 0;
|
|
fm_u8 seek_space = 10;
|
|
fm_u16 Start_Freq = 8750;
|
|
fm_u8 NF_Space = 41;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
//FM radio seek space,5:50KHZ; 1:100KHZ; 2:200KHZ
|
|
if (fmr_data.cfg_data.seek_space == 5) {
|
|
seek_space = 5;
|
|
} else if (fmr_data.cfg_data.seek_space == 2) {
|
|
seek_space = 20;
|
|
} else {
|
|
seek_space = 10;
|
|
}
|
|
if (fmr_data.cfg_data.band == FM_BAND_JAPAN)/* Japan band 76MHz ~ 90MHz */ {
|
|
band_channel_no = (9600-7600)/seek_space + 1;
|
|
Start_Freq = 7600;
|
|
NF_Space = 400/seek_space;
|
|
} else if (fmr_data.cfg_data.band == FM_BAND_JAPANW)/* Japan wideband 76MHZ ~ 108MHz */ {
|
|
band_channel_no = (10800-7600)/seek_space + 1;
|
|
Start_Freq = 7600;
|
|
NF_Space = 640/seek_space;
|
|
} else/* US/Europe band 87.5MHz ~ 108MHz (DEFAULT) */ {
|
|
band_channel_no = (10800-8750)/seek_space + 1;
|
|
Start_Freq = 8750;
|
|
NF_Space = 410/seek_space;
|
|
}
|
|
|
|
ret = FMR_scan_Channels(idx, scan_tbl, max_cnt, band_channel_no, Start_Freq, seek_space, NF_Space);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int FMR_stop_scan(int idx)
|
|
{
|
|
UNUSED(idx);
|
|
fmr_data.scan_stop = fm_true;
|
|
return 0;
|
|
}
|
|
|
|
int FMR_turn_on_off_rds(int idx, int onoff)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).turn_on_off_rds)
|
|
ret = FMR_cbk_tbl(idx).turn_on_off_rds(FMR_fd(idx), onoff);
|
|
if (ret) {
|
|
LOGE("%s, failed\n", __func__);
|
|
}
|
|
LOGD("%s, [onoff=%d] [ret=%d]\n", __func__, onoff, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_read_rds_data(int idx, uint16_t *rds_status)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).read_rds_data);
|
|
FMR_ASSERT(rds_status);
|
|
|
|
ret = FMR_cbk_tbl(idx).read_rds_data(FMR_fd(idx), &fmr_data.rds, rds_status);
|
|
|
|
LOGD("%s, [status=0x%04x] , [ret=%d]\n", __func__, *rds_status, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int FMR_active_af(int idx, uint16_t orig_pi, uint16_t *ret_freq)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).active_af);
|
|
FMR_ASSERT(ret_freq);
|
|
ret = FMR_cbk_tbl(idx).active_af(FMR_fd(idx),
|
|
&fmr_data.rds,
|
|
&fmr_data.cfg_data,
|
|
orig_pi,
|
|
fmr_data.cur_freq,
|
|
ret_freq);
|
|
if ((ret == 0) && (*ret_freq != fmr_data.cur_freq)) {
|
|
fmr_data.cur_freq = *ret_freq;
|
|
LOGI("active AF OK, new channel[freq=%d]\n", fmr_data.cur_freq);
|
|
}
|
|
if(fmr_data.cfg_data.seek_space != 5) {
|
|
*ret_freq = *ret_freq/10;
|
|
}
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_active_ta(int idx, uint16_t *ret_freq)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).active_ta);
|
|
FMR_ASSERT(ret_freq);
|
|
ret = FMR_cbk_tbl(idx).active_ta(FMR_fd(idx),
|
|
&fmr_data.rds,
|
|
fmr_data.cfg_data.band,
|
|
fmr_data.cur_freq,
|
|
&fmr_data.backup_freq,
|
|
ret_freq);
|
|
if((ret == 0) && (*ret_freq != fmr_data.cur_freq)){
|
|
fmr_data.cur_freq = *ret_freq;
|
|
LOGI("active TA OK, new channel[freq=%d]\n", fmr_data.cur_freq);
|
|
}
|
|
if(fmr_data.cfg_data.seek_space != 5) {
|
|
*ret_freq = *ret_freq/10;
|
|
}
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_deactive_ta(int idx, uint16_t *ret_freq)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).deactive_ta);
|
|
FMR_ASSERT(ret_freq);
|
|
ret = FMR_cbk_tbl(idx).deactive_ta(FMR_fd(idx),
|
|
&fmr_data.rds,
|
|
fmr_data.cfg_data.band,
|
|
fmr_data.cur_freq,
|
|
&fmr_data.backup_freq,
|
|
ret_freq);
|
|
if((ret == 0) && (*ret_freq != fmr_data.cur_freq)){
|
|
fmr_data.cur_freq = *ret_freq;
|
|
LOGI("deactive TA OK, new channel[freq=%d]\n", fmr_data.cur_freq);
|
|
}
|
|
if(fmr_data.cfg_data.seek_space != 5) {
|
|
*ret_freq = *ret_freq/10;
|
|
}
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_ana_switch(int idx, int antenna)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).ana_switch);
|
|
|
|
if (fmr_data.cfg_data.short_ana_sup == true) {
|
|
ret = FMR_cbk_tbl(idx).ana_switch(FMR_fd(idx), antenna);
|
|
if (ret) {
|
|
LOGE("%s failed, [ret=%d]\n", __func__, ret);
|
|
}
|
|
} else {
|
|
LOGW("FM antenna switch not support!\n");
|
|
ret = -ERR_UNSUPT_SHORTANA;
|
|
}
|
|
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_badratio(int idx, int *badratio)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_badratio);
|
|
FMR_ASSERT(badratio);
|
|
|
|
ret = FMR_cbk_tbl(idx).get_badratio(FMR_fd(idx), badratio);
|
|
if (ret){
|
|
*badratio = 0;
|
|
LOGE("%s failed, %s\n", __func__, FMR_strerr());
|
|
}
|
|
|
|
LOGD("%s, [badratio=%d] [ret=%d]\n", __func__, *badratio, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_stereomono(int idx, int *stemono)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_stereomono);
|
|
FMR_ASSERT(stemono);
|
|
|
|
ret = FMR_cbk_tbl(idx).get_stereomono(FMR_fd(idx), stemono);
|
|
if (ret){
|
|
*stemono = 0;
|
|
LOGE("%s failed, %s\n", __func__, FMR_strerr());
|
|
}
|
|
|
|
LOGD("%s, [stemono=%d] [ret=%d]\n", __func__, *stemono, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_set_stereomono(int idx, int stemono)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).set_stereomono);
|
|
|
|
ret = FMR_cbk_tbl(idx).set_stereomono(FMR_fd(idx), stemono);
|
|
if (ret){
|
|
LOGE("%s failed, %s\n", __func__, FMR_strerr());
|
|
}
|
|
|
|
LOGD("%s, [stemono=%d] [ret=%d]\n", __func__, stemono, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_caparray(int idx, int *caparray)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_caparray);
|
|
FMR_ASSERT(caparray);
|
|
|
|
ret = FMR_cbk_tbl(idx).get_caparray(FMR_fd(idx), caparray);
|
|
if (ret){
|
|
*caparray = 0;
|
|
LOGE("%s failed, %s\n", __func__, FMR_strerr());
|
|
}
|
|
|
|
LOGD("%s, [caparray=%d] [ret=%d]\n", __func__, *caparray, ret);
|
|
return ret;
|
|
}
|
|
|
|
int FMR_get_hw_info(int idx, int **info, int *info_len)
|
|
{
|
|
int ret = 0;
|
|
static int inited = 0;
|
|
static int info_array[10] = {0};
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).get_hw_info);
|
|
FMR_ASSERT(info);
|
|
FMR_ASSERT(info_len);
|
|
|
|
if(!inited){
|
|
ret = FMR_cbk_tbl(idx).get_hw_info(FMR_fd(idx), &fmr_data.hw_info);
|
|
if(ret >= 0){
|
|
inited = 1; //get hw info success
|
|
}
|
|
}
|
|
|
|
info_array[0] = fmr_data.hw_info.chip_id;
|
|
info_array[1] = fmr_data.hw_info.eco_ver;
|
|
info_array[2] = fmr_data.hw_info.rom_ver;
|
|
info_array[3] = fmr_data.hw_info.patch_ver;
|
|
|
|
*info = info_array;
|
|
*info_len = sizeof(struct fm_hw_info)/sizeof(int);
|
|
|
|
LOGD("chip:0x%08x, eco:0x%08x, rom:0x%08x, patch: 0x%08x\n", info_array[0], info_array[1], info_array[2], info_array[3]);
|
|
LOGD("%s, [ret=%d]\n", __func__, ret);
|
|
return ret;
|
|
}
|
|
/*
|
|
th_idx:
|
|
threshold type: 0, RSSI. 1,desense RSSI. 2,SMG.
|
|
th_val: threshold value*/
|
|
int FMR_EMSetTH(int idx, int th_idx, int th_val)
|
|
{
|
|
int ret = -1;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).set_search_threshold);
|
|
ret=FMR_cbk_tbl(idx).set_search_threshold(FMR_fd(idx),th_idx,th_val);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int FMR_EM_CQI_logger(int idx,uint16_t cycle)
|
|
{
|
|
int ret = -1;
|
|
fm_full_cqi_log_t log_setting;
|
|
uint i = 0;
|
|
|
|
if (idx < 0 || idx >= FMR_MAX_IDX) {
|
|
return -1;
|
|
}
|
|
|
|
FMR_ASSERT(FMR_cbk_tbl(idx).full_cqi_logger);
|
|
|
|
//log_setting.cycle = cycle;
|
|
if(fmr_data.cfg_data.seek_space == 5) {
|
|
log_setting.lower = FM_FREQ_MIN * 10;
|
|
log_setting.upper = FM_FREQ_MAX * 10;
|
|
} else {
|
|
log_setting.lower = FM_FREQ_MIN;
|
|
log_setting.upper = FM_FREQ_MAX;
|
|
}
|
|
log_setting.space = 0x2;
|
|
|
|
for(i = 0;i < cycle; i++)
|
|
{
|
|
|
|
log_setting.cycle = i;
|
|
ret = FMR_cbk_tbl(idx).full_cqi_logger(FMR_fd(idx),&log_setting);
|
|
|
|
LOGD("%s, [%d]\n", __func__, i);
|
|
}
|
|
|
|
//ret = FMR_cbk_tbl(idx).full_cqi_logger(FMR_fd(idx),&log_setting);
|
|
|
|
return ret;
|
|
}
|
|
|