Home | History | Annotate | Download | only in fmr
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*******************************************************************
     18  * FM JNI core
     19  * return -1 if error occured. else return needed value.
     20  * if return type is char *, return NULL if error occured.
     21  * Do NOT return value access paramater.
     22  *
     23  * FM JNI core should be independent from lower layer, that means
     24  * there should be no low layer dependent data struct in FM JNI core
     25  *
     26  * Naming rule: FMR_n(paramter Micro), FMR_v(functions), fmr_n(global param)
     27  * pfmr_n(global paramter pointer)
     28  *
     29  *******************************************************************/
     30 
     31 #include "fmr.h"
     32 
     33 #ifdef LOG_TAG
     34 #undef LOG_TAG
     35 #endif
     36 #define LOG_TAG "FMLIB_CORE"
     37 
     38 #define FMR_MAX_IDX 1
     39 
     40 struct fmr_ds fmr_data;
     41 struct fmr_ds *pfmr_data[FMR_MAX_IDX] = {0};
     42 #define FMR_fd(idx) ((pfmr_data[idx])->fd)
     43 #define FMR_err(idx) ((pfmr_data[idx])->err)
     44 #define FMR_chip(idx) ((pfmr_data[idx])->cfg_data.chip)
     45 #define FMR_low_band(idx) ((pfmr_data[idx])->cfg_data.low_band)
     46 #define FMR_high_band(idx) ((pfmr_data[idx])->cfg_data.high_band)
     47 #define FMR_seek_space(idx) ((pfmr_data[idx])->cfg_data.seek_space)
     48 #define FMR_max_scan_num(idx) ((pfmr_data[idx])->cfg_data.max_scan_num)
     49 #define FMR_cbk_tbl(idx) ((pfmr_data[idx])->tbl)
     50 #define FMR_cust_hdler(idx) ((pfmr_data[idx])->custom_handler)
     51 #define FMR_get_cfg(idx) ((pfmr_data[idx])->get_cfg)
     52 
     53 int FMR_get_cfgs(int idx)
     54 {
     55     int ret = -1;
     56     FMR_cust_hdler(idx) = NULL;
     57     FMR_get_cfg(idx) = NULL;
     58 
     59     FMR_cust_hdler(idx) = dlopen(CUST_LIB_NAME, RTLD_NOW);
     60     if (FMR_cust_hdler(idx) == NULL) {
     61         LOGE("%s failed, %s\n", __FUNCTION__, dlerror());
     62         //FMR_seterr(ERR_LD_LIB);
     63     } else {
     64         *(void **) (&FMR_get_cfg(idx)) = dlsym(FMR_cust_hdler(idx), "CUST_get_cfg");
     65         if (FMR_get_cfg(idx) == NULL) {
     66             LOGE("%s failed, %s\n", __FUNCTION__, dlerror());
     67             //FMR_seterr(ERR_FIND_CUST_FNUC);
     68         } else {
     69             LOGI("Go to run cust function\n");
     70             (*FMR_get_cfg(idx))(&(pfmr_data[idx]->cfg_data));
     71             LOGI("OK\n");
     72             ret = 0;
     73         }
     74         //dlclose(FMR_cust_hdler(idx));
     75         FMR_cust_hdler(idx) = NULL;
     76         FMR_get_cfg(idx) = NULL;
     77     }
     78     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));
     79 
     80     return ret;
     81 }
     82 
     83 int FMR_chk_cfg_data(int idx)
     84 {
     85     //TODO Need check? how to check?
     86     return 0;
     87 }
     88 
     89 static void sig_alarm(int sig)
     90 {
     91     LOGI("+++Receive sig %d\n", sig);
     92     return;
     93 }
     94 
     95 int FMR_init()
     96 {
     97     int idx;
     98     int ret = 0;
     99     //signal(4, sig_alarm);
    100 
    101     for (idx=0; idx<FMR_MAX_IDX; idx++) {
    102         if (pfmr_data[idx] == NULL) {
    103             break;
    104         }
    105     }
    106     LOGI("FMR idx = %d\n", idx);
    107     if (idx == FMR_MAX_IDX) {
    108         //FMR_seterr(ERR_NO_MORE_IDX);
    109         return -1;
    110     }
    111 
    112     /*The best way here is to call malloc to alloc mem for each idx,but
    113     I do not know where to release it, so use static global param instead*/
    114     pfmr_data[idx] = &fmr_data;
    115     memset(pfmr_data[idx], 0, sizeof(struct fmr_ds));
    116 
    117     if (FMR_get_cfgs(idx) < 0) {
    118         LOGI("FMR_get_cfgs failed\n");
    119         goto fail;
    120     }
    121 
    122     if (FMR_chk_cfg_data(idx) < 0) {
    123         LOGI("FMR_chk_cfg_data failed\n");
    124         goto fail;
    125     }
    126 
    127     pfmr_data[idx]->init_func = FM_interface_init;
    128     if (pfmr_data[idx]->init_func == NULL) {
    129         LOGE("%s init_func error, %s\n", __func__, dlerror());
    130         goto fail;
    131     } else {
    132         LOGI("Go to run init function\n");
    133         (*pfmr_data[idx]->init_func)(&(pfmr_data[idx]->tbl));
    134         LOGI("OK\n");
    135         ret = 0;
    136     }
    137 
    138     return idx;
    139 
    140 fail:
    141     pfmr_data[idx] = NULL;
    142 
    143     return -1;
    144 }
    145 
    146 int FMR_open_dev(int idx)
    147 {
    148     int ret = 0;
    149     int real_chip;
    150 
    151     FMR_ASSERT(FMR_cbk_tbl(idx).open_dev);
    152 
    153     ret = FMR_cbk_tbl(idx).open_dev(FM_DEV_NAME, &FMR_fd(idx));
    154     if (ret || FMR_fd(idx) < 0) {
    155         LOGE("%s failed, [fd=%d]\n", __func__, FMR_fd(idx));
    156         return ret;
    157     }
    158 
    159     //Check if customer's cfg matchs driver.
    160     ret = FMR_get_chip_id(idx, &real_chip);
    161     if (FMR_chip(idx) != real_chip) {
    162         LOGE("%s, Chip config error. 0x%x\n", __func__, real_chip);
    163         ret = FMR_cbk_tbl(idx).close_dev(FMR_fd(idx));
    164         return ret;
    165     }
    166 
    167     LOGD("%s, [fd=%d] [chipid=0x%x] [ret=%d]\n", __func__, FMR_fd(idx), real_chip, ret);
    168     return ret;
    169 }
    170 
    171 int FMR_close_dev(int idx)
    172 {
    173     int ret = 0;
    174 
    175     FMR_ASSERT(FMR_cbk_tbl(idx).close_dev);
    176     ret = FMR_cbk_tbl(idx).close_dev(FMR_fd(idx));
    177     LOGD("%s, [fd=%d] [ret=%d]\n", __func__, FMR_fd(idx), ret);
    178     return ret;
    179 }
    180 
    181 int FMR_pwr_up(int idx, int freq)
    182 {
    183     int ret = 0;
    184 
    185     FMR_ASSERT(FMR_cbk_tbl(idx).pwr_up);
    186 
    187     LOGI("%s,[freq=%d]\n", __func__, freq);
    188     if (freq < fmr_data.cfg_data.low_band || freq > fmr_data.cfg_data.high_band) {
    189         LOGE("%s error freq: %d\n", __func__, freq);
    190         ret = -ERR_INVALID_PARA;
    191         return ret;
    192     }
    193     ret = FMR_cbk_tbl(idx).pwr_up(FMR_fd(idx), fmr_data.cfg_data.band, freq);
    194     if (ret) {
    195         LOGE("%s failed, [ret=%d]\n", __func__, ret);
    196     }
    197     fmr_data.cur_freq = freq;
    198     LOGD("%s, [ret=%d]\n", __func__, ret);
    199     return ret;
    200 }
    201 
    202 int FMR_pwr_down(int idx, int type)
    203 {
    204     int ret = 0;
    205 
    206     FMR_ASSERT(FMR_cbk_tbl(idx).pwr_down);
    207     ret = FMR_cbk_tbl(idx).pwr_down(FMR_fd(idx), type);
    208     LOGD("%s, [ret=%d]\n", __func__, ret);
    209     return ret;
    210 }
    211 
    212 int FMR_get_chip_id(int idx, int *chipid)
    213 {
    214     int ret = 0;
    215 
    216     FMR_ASSERT(FMR_cbk_tbl(idx).get_chip_id);
    217     FMR_ASSERT(chipid);
    218 
    219     ret = FMR_cbk_tbl(idx).get_chip_id(FMR_fd(idx), chipid);
    220     if (ret) {
    221         LOGE("%s failed, %s\n", __func__, FMR_strerr());
    222         *chipid = -1;
    223     }
    224     LOGD("%s, [ret=%d]\n", __func__, ret);
    225     return ret;
    226 }
    227 
    228 int FMR_get_ps(int idx, uint8_t **ps, int *ps_len)
    229 {
    230     int ret = 0;
    231 
    232     FMR_ASSERT(FMR_cbk_tbl(idx).get_ps);
    233     FMR_ASSERT(ps);
    234     FMR_ASSERT(ps_len);
    235     ret = FMR_cbk_tbl(idx).get_ps(FMR_fd(idx), &fmr_data.rds, ps, ps_len);
    236     LOGD("%s, [ret=%d]\n", __func__, ret);
    237     return ret;
    238 }
    239 
    240 int FMR_get_rt(int idx, uint8_t **rt, int *rt_len)
    241 {
    242     int ret = 0;
    243 
    244     FMR_ASSERT(FMR_cbk_tbl(idx).get_rt);
    245     FMR_ASSERT(rt);
    246     FMR_ASSERT(rt_len);
    247 
    248     ret = FMR_cbk_tbl(idx).get_rt(FMR_fd(idx), &fmr_data.rds, rt, rt_len);
    249     LOGD("%s, [ret=%d]\n", __func__, ret);
    250     return ret;
    251 }
    252 
    253 int FMR_tune(int idx, int freq)
    254 {
    255     int ret = 0;
    256 
    257     FMR_ASSERT(FMR_cbk_tbl(idx).tune);
    258 
    259     ret = FMR_cbk_tbl(idx).tune(FMR_fd(idx), freq, fmr_data.cfg_data.band);
    260     if (ret) {
    261         LOGE("%s failed, [ret=%d]\n", __func__, ret);
    262     }
    263     fmr_data.cur_freq = freq;
    264     LOGD("%s, [freq=%d] [ret=%d]\n", __func__, freq, ret);
    265     return ret;
    266 }
    267 
    268 /*return: fm_true: desense, fm_false: not desene channel*/
    269 fm_bool FMR_DensenseDetect(fm_s32 idx, fm_u16 ChannelNo, fm_s32 RSSI)
    270 {
    271     fm_u8 bDesenseCh = 0;
    272 
    273     bDesenseCh = FMR_cbk_tbl(idx).desense_check(FMR_fd(idx), ChannelNo, RSSI);
    274     if (bDesenseCh == 1) {
    275         return fm_true;
    276     }
    277     return fm_false;
    278 }
    279 
    280 fm_bool FMR_SevereDensense(fm_u16 ChannelNo, fm_s32 RSSI)
    281 {
    282     fm_s32 i = 0, j = 0;
    283     struct fm_fake_channel_t *chan_info = fmr_data.cfg_data.fake_chan;
    284 
    285     ChannelNo /= 10;
    286 
    287     for (i=0; i<chan_info->size; i++) {
    288         if (ChannelNo == chan_info->chan[i].freq) {
    289             //if (RSSI < FM_SEVERE_RSSI_TH)
    290             if (RSSI < chan_info->chan[i].rssi_th) {
    291                 LOGI(" SevereDensense[%d] RSSI[%d]\n", ChannelNo,RSSI);
    292                 return fm_true;
    293             } else {
    294                 break;
    295             }
    296         }
    297     }
    298     return fm_false;
    299 }
    300 #if (FMR_NOISE_FLOORT_DETECT==1)
    301 /*return TRUE:get noise floor freq*/
    302 fm_bool FMR_NoiseFloorDetect(fm_bool *rF, fm_s32 rssi, fm_s32 *F_rssi)
    303 {
    304     if (rF[0] == fm_true) {
    305         if (rF[1] == fm_true) {
    306             F_rssi[2] = rssi;
    307             rF[2] = fm_true;
    308             return fm_true;
    309         } else {
    310             F_rssi[1] = rssi;
    311             rF[1] = fm_true;
    312         }
    313     } else {
    314         F_rssi[0] = rssi;
    315         rF[0] = fm_true;
    316     }
    317     return fm_false;
    318 }
    319 #endif
    320 
    321 /*check the cur_freq->freq is valid or not
    322 return fm_true : need check cur_freq->valid
    323          fm_false: check faild, should stop seek
    324 */
    325 static fm_bool FMR_Seek_TuneCheck(int idx, fm_softmute_tune_t *cur_freq)
    326 {
    327     int ret = 0;
    328     if (fmr_data.scan_stop == fm_true) {
    329         ret = FMR_tune(idx,fmr_data.cur_freq);
    330         LOGI("seek stop!!! tune ret=%d",ret);
    331         return fm_false;
    332     }
    333     ret = FMR_cbk_tbl(idx).soft_mute_tune(FMR_fd(idx), cur_freq);
    334     if (ret) {
    335         LOGE("soft mute tune, failed:[%d]\n",ret);
    336         cur_freq->valid = fm_false;
    337         return fm_true;
    338     }
    339     if (cur_freq->valid == fm_true)/*get valid channel*/ {
    340         if (FMR_DensenseDetect(idx, cur_freq->freq, cur_freq->rssi) == fm_true) {
    341             LOGI("desense channel detected:[%d] \n", cur_freq->freq);
    342             cur_freq->valid = fm_false;
    343             return fm_true;
    344         }
    345         if (FMR_SevereDensense(cur_freq->freq, cur_freq->rssi) == fm_true) {
    346             LOGI("sever desense channel detected:[%d] \n", cur_freq->freq);
    347             cur_freq->valid = fm_false;
    348             return fm_true;
    349         }
    350         LOGI("seek result freq:[%d] \n", cur_freq->freq);
    351     }
    352     return fm_true;
    353 }
    354 /*
    355 check more 2 freq, curfreq: current freq, seek_dir: 1,forward. 0,backword
    356 */
    357 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)
    358 {
    359     fm_s32 i;
    360     fm_softmute_tune_t cur_freq;
    361     cur_freq.freq = validfreq->freq;
    362 
    363     for (i=0; i<2; i++) {
    364         if (seek_dir)/*forward*/ {
    365             if (cur_freq.freq + step > max_freq) {
    366                 return 0;
    367             }
    368             cur_freq.freq += step;
    369         } else/*backward*/ {
    370             if (cur_freq.freq - step < min_freq) {
    371                 return 0;
    372             }
    373             cur_freq.freq -= step;
    374         }
    375         if (FMR_Seek_TuneCheck(idx, &cur_freq) == fm_true) {
    376             if (cur_freq.valid == fm_true) {
    377                 if (cur_freq.rssi > validfreq->rssi) {
    378                     validfreq->freq = cur_freq.freq;
    379                     validfreq->rssi = cur_freq.rssi;
    380                     LOGI("seek cover last by freq=%d",cur_freq.freq);
    381                 }
    382             }
    383         } else {
    384             return -1;
    385         }
    386     }
    387     return 0;
    388 }
    389 
    390 /*check the a valid channel
    391 return -1 : seek fail
    392          0: seek success
    393 */
    394 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)
    395 {
    396     fm_s32 i, ret = 0;
    397     fm_softmute_tune_t cur_freq;
    398 
    399     if (dir == 1)/*forward*/ {
    400         for (i=((start_freq-min_freq)/seek_space+1); i<band_channel_no; i++) {
    401             cur_freq.freq = min_freq + seek_space*i;
    402             LOGI("i=%d, freq=%d-----1",i,cur_freq.freq);
    403             ret = FMR_Seek_TuneCheck(idx, &cur_freq);
    404             if (ret == fm_false) {
    405                 return -1;
    406             } else {
    407                 if (cur_freq.valid == fm_false) {
    408                     continue;
    409                 } else {
    410                     if (FMR_Seek_More(idx, &cur_freq, dir, seek_space, min_freq, max_freq) == 0) {
    411                         *ret_freq = cur_freq.freq;
    412                         *rssi_tmp = cur_freq.rssi;
    413                         return 0;
    414                     } else {
    415                         return -1;
    416                     }
    417                 }
    418             }
    419         }
    420         for (i=0; i<((start_freq-min_freq)/seek_space); i++) {
    421             cur_freq.freq = min_freq + seek_space*i;
    422             LOGI("i=%d, freq=%d-----2",i,cur_freq.freq);
    423             ret = FMR_Seek_TuneCheck(idx, &cur_freq);
    424             if (ret == fm_false) {
    425                 return -1;
    426             } else {
    427                 if (cur_freq.valid == fm_false) {
    428                     continue;
    429                 } else {
    430                     if (FMR_Seek_More(idx, &cur_freq, dir, seek_space, min_freq, max_freq) == 0) {
    431                         *ret_freq = cur_freq.freq;
    432                         *rssi_tmp = cur_freq.rssi;
    433                         return 0;
    434                     } else {
    435                         return -1;
    436                     }
    437                 }
    438             }
    439         }
    440     } else/*backward*/ {
    441         for (i=((start_freq-min_freq)/seek_space-1); i>=0; i--) {
    442             cur_freq.freq = min_freq + seek_space*i;
    443             LOGI("i=%d, freq=%d-----3",i,cur_freq.freq);
    444             ret = FMR_Seek_TuneCheck(idx, &cur_freq);
    445             if (ret == fm_false) {
    446                 return -1;
    447             } else {
    448                 if (cur_freq.valid == fm_false) {
    449                     continue;
    450                 } else {
    451                     if (FMR_Seek_More(idx, &cur_freq, dir, seek_space, min_freq, max_freq) == 0) {
    452                         *ret_freq = cur_freq.freq;
    453                         *rssi_tmp = cur_freq.rssi;
    454                         return 0;
    455                     } else {
    456                         return -1;
    457                     }
    458                 }
    459             }
    460         }
    461         for (i=(band_channel_no-1); i>((start_freq-min_freq)/seek_space); i--) {
    462             cur_freq.freq = min_freq + seek_space*i;
    463             LOGI("i=%d, freq=%d-----4",i,cur_freq.freq);
    464             ret = FMR_Seek_TuneCheck(idx, &cur_freq);
    465             if (ret == fm_false) {
    466                 return -1;
    467             } else {
    468                 if (cur_freq.valid == fm_false) {
    469                     continue;
    470                 } else {
    471                     if (FMR_Seek_More(idx, &cur_freq, dir,seek_space, min_freq, max_freq) == 0) {
    472                         *ret_freq = cur_freq.freq;
    473                         *rssi_tmp = cur_freq.rssi;
    474                         return 0;
    475                     } else {
    476                         return -1;
    477                     }
    478                 }
    479             }
    480         }
    481     }
    482 
    483     *ret_freq = start_freq;
    484     return 0;
    485 }
    486 
    487 int FMR_seek(int idx, int start_freq, int dir, int *ret_freq)
    488 {
    489     fm_s32 ret = 0, i, j;
    490     fm_softmute_tune_t cur_freq;
    491     fm_s32 band_channel_no = 0;
    492     fm_u8 seek_space = 10;
    493     fm_u16 min_freq, max_freq;
    494     int rssi;
    495 
    496     if ((start_freq < 7600) || (start_freq > 10800)) /*need replace by macro*/ {
    497         LOGE("%s error start_freq: %d\n", __func__, start_freq);
    498         return -ERR_INVALID_PARA;
    499     }
    500 
    501     //FM radio seek space,5:50KHZ; 1:100KHZ; 2:200KHZ
    502     if (fmr_data.cfg_data.seek_space == 5) {
    503         seek_space = 5;
    504     } else if (fmr_data.cfg_data.seek_space == 2) {
    505         seek_space = 20;
    506     } else {
    507         seek_space = 10;
    508     }
    509     if (fmr_data.cfg_data.band == FM_BAND_JAPAN)/* Japan band	   76MHz ~ 90MHz */ {
    510         band_channel_no = (9600-7600)/seek_space + 1;
    511         min_freq = 7600;
    512         max_freq = 9600;
    513     } else if (fmr_data.cfg_data.band == FM_BAND_JAPANW)/* Japan wideband  76MHz ~ 108MHz */ {
    514         band_channel_no = (10800-7600)/seek_space + 1;
    515         min_freq = 7600;
    516         max_freq = 10800;
    517     } else/* US/Europe band  87.5MHz ~ 108MHz (DEFAULT) */ {
    518         band_channel_no = (10800-8750)/seek_space + 1;
    519         min_freq = 8750;
    520         max_freq = 10800;
    521     }
    522 
    523     fmr_data.scan_stop = fm_false;
    524     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);
    525 
    526     ret = FMR_seek_Channel(idx, start_freq, min_freq, max_freq, band_channel_no, seek_space, dir, ret_freq, &rssi);
    527 
    528     return ret;
    529 }
    530 
    531 int FMR_set_mute(int idx, int mute)
    532 {
    533     int ret = 0;
    534 
    535     FMR_ASSERT(FMR_cbk_tbl(idx).set_mute)
    536 
    537     if ((mute < 0) || (mute > 1)) {
    538         LOGE("%s error param mute:  %d\n", __func__, mute);
    539     }
    540 
    541     ret = FMR_cbk_tbl(idx).set_mute(FMR_fd(idx), mute);
    542     if (ret) {
    543         LOGE("%s failed, %s\n", __func__, FMR_strerr());
    544     }
    545     LOGD("%s, [mute=%d] [ret=%d]\n", __func__, mute, ret);
    546     return ret;
    547 }
    548 
    549 int FMR_is_rdsrx_support(int idx, int *supt)
    550 {
    551     int ret = 0;
    552 
    553     FMR_ASSERT(FMR_cbk_tbl(idx).is_rdsrx_support);
    554     FMR_ASSERT(supt);
    555 
    556     ret = FMR_cbk_tbl(idx).is_rdsrx_support(FMR_fd(idx), supt);
    557     if (ret) {
    558         *supt = 0;
    559         LOGE("%s, failed\n", __func__);
    560     }
    561     LOGD("%s, [supt=%d] [ret=%d]\n", __func__, *supt, ret);
    562     return ret;
    563 }
    564 
    565 int FMR_Pre_Search(int idx)
    566 {
    567     //avoid scan stop flag clear if stop cmd send before pre-search finish
    568     fmr_data.scan_stop = fm_false;
    569     FMR_ASSERT(FMR_cbk_tbl(idx).pre_search);
    570     FMR_cbk_tbl(idx).pre_search(FMR_fd(idx));
    571     return 0;
    572 }
    573 
    574 int FMR_Restore_Search(int idx)
    575 {
    576     FMR_ASSERT(FMR_cbk_tbl(idx).restore_search);
    577     FMR_cbk_tbl(idx).restore_search(FMR_fd(idx));
    578     return 0;
    579 }
    580 
    581 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)
    582 {
    583     fm_s32 ret = 0, Num = 0, i, j;
    584     fm_u32 ChannelNo = 0;
    585     fm_softmute_tune_t cur_freq;
    586     static struct fm_cqi SortData[CQI_CH_NUM_MAX];
    587     fm_bool LastExist = fm_false;
    588     struct fm_cqi swap;
    589 #if (FMR_NOISE_FLOORT_DETECT==1)
    590     fm_s32 Pacc = 0, Nacc = 0;
    591     fm_s32 NF = 0;
    592     fm_bool F[3] = {fm_false, fm_false, fm_false};
    593     fm_s32 F_Rssi[3] = {0};
    594     fm_u8 NF_Idx = 0;
    595 #endif
    596 
    597     memset(SortData, 0, CQI_CH_NUM_MAX*sizeof(struct fm_cqi));
    598     LOGI("band_channel_no=[%d], seek_space=%d, start freq=%d\n", band_channel_no,seek_space,Start_Freq);
    599     for (i=0; i<band_channel_no; i++) {
    600         if (fmr_data.scan_stop == fm_true) {
    601             FMR_Restore_Search(idx);
    602             ret = FMR_tune(idx, fmr_data.cur_freq);
    603             LOGI("scan stop!!! tune ret=%d",ret);
    604             return -1;
    605         }
    606         cur_freq.freq = Start_Freq + seek_space*i;
    607         ret = FMR_cbk_tbl(idx).soft_mute_tune(FMR_fd(idx), &cur_freq);
    608         if (ret) {
    609             LOGE("soft mute tune, failed:[%d]\n",ret);
    610             LastExist = fm_false;
    611             continue;
    612         }
    613         if (cur_freq.valid == fm_true)/*get valid channel*/ {
    614 #if (FMR_NOISE_FLOORT_DETECT==1)
    615             memset(F, fm_false, sizeof(F));
    616 #endif
    617             if (FMR_DensenseDetect(idx, cur_freq.freq, cur_freq.rssi) == fm_true) {
    618                 LOGI("desense channel detected:[%d] \n", cur_freq.freq);
    619                 LastExist = fm_false;
    620                 continue;
    621             }
    622             if ((LastExist == fm_true) && (Num > 0)) /*neighbor channel*/ {
    623                 if (cur_freq.rssi>SortData[Num-1].rssi)/*save current freq and cover last channel*/ {
    624                     if (FMR_SevereDensense(cur_freq.freq, cur_freq.rssi) == fm_true) {
    625                         LastExist = fm_false;
    626                         continue;
    627                     }
    628                     SortData[Num-1].ch=cur_freq.freq;
    629                     SortData[Num-1].rssi=cur_freq.rssi;
    630                     SortData[Num-1].reserve = 1;
    631                     LOGI("cover last channel \n");
    632                 } else/*ignore current freq*/ {
    633                     LastExist = fm_false;
    634                     continue;
    635                 }
    636             } else/*save current*/ {
    637                 if (FMR_SevereDensense(cur_freq.freq, cur_freq.rssi) == fm_true) {
    638                     LastExist = fm_false;
    639                     continue;
    640                 }
    641                 SortData[Num].ch = cur_freq.freq;
    642                 SortData[Num].rssi = cur_freq.rssi;
    643                 SortData[Num].reserve = 1;
    644                 Num++;
    645                 LastExist = fm_true;
    646                 LOGI("Num++:[%d] \n", Num);
    647             }
    648         } else {
    649 #if (FMR_NOISE_FLOORT_DETECT==1)
    650             if (FMR_DensenseDetect(idx, cur_freq.freq, cur_freq.rssi) == fm_false) {
    651                 if (FMR_NoiseFloorDetect(F, cur_freq.rssi, F_Rssi) == fm_true) {
    652                     Pacc += F_Rssi[1];
    653                     Nacc++;
    654                     /*check next freq*/
    655                     F[0] = F[1];
    656                     F_Rssi[0] = F_Rssi[1];
    657                     F[1] = F[2];
    658                     F_Rssi[1] = F_Rssi[2];
    659                     F[2] = fm_false;
    660                     F_Rssi[2] = 0;
    661                     LOGI("FM Noise FLoor:Pacc=[%d] Nacc=[%d] \n", Pacc,Nacc);
    662                 }
    663             } else {
    664                 memset(F, fm_false, sizeof(F));
    665             }
    666 #endif
    667             LastExist = fm_false;
    668         }
    669 #if (FMR_NOISE_FLOORT_DETECT==1)
    670         if (((i%NF_Space) == 0) && (i != 0)) {
    671             if (Nacc > 0) {
    672                 NF = Pacc/Nacc;
    673             } else {
    674                 NF = RSSI_TH-FM_NOISE_FLOOR_OFFSET;
    675             }
    676             Pacc = 0;
    677             Nacc = 0;
    678             for (j=NF_Idx; j<Num; j++) {
    679                 if (SortData[j].rssi < (NF+FM_NOISE_FLOOR_OFFSET)) {
    680                     LOGI("FM Noise FLoor Detected:freq=[%d] NF=[%d] \n", SortData[j].ch,NF);
    681                     SortData[j].reserve = 0;
    682                 }
    683             }
    684             NF_Idx = j;
    685             LOGI("FM Noise FLoor NF_Idx[%d] \n", NF_Idx);
    686         }
    687 #endif
    688     }
    689     LOGI("get channel no.[%d] \n", Num);
    690     if (Num == 0)/*get nothing*/ {
    691         *max_cnt = 0;
    692         FMR_Restore_Search(idx);
    693         return -1;
    694     }
    695     for (i=0; i<Num; i++)/*debug*/ {
    696         LOGI("[%d]:%d \n", i,SortData[i].ch);
    697     }
    698 
    699     switch (fmr_data.cfg_data.scan_sort)
    700     {
    701         case FM_SCAN_SORT_UP:
    702         case FM_SCAN_SORT_DOWN:
    703             {
    704                 LOGI("Start sort \n");
    705                 //do sort: insert sort algorithm
    706                 for (i = 1; i < Num; i++) {
    707                     for (j = i; (j > 0) && ((FM_SCAN_SORT_DOWN == fmr_data.cfg_data.scan_sort) ? (SortData[j-1].rssi \
    708                         < SortData[j].rssi) : (SortData[j-1].rssi > SortData[j].rssi)); j--) {
    709                         memcpy(&swap, &SortData[j], sizeof(struct fm_cqi));
    710                         memcpy(&SortData[j], &SortData[j-1], sizeof(struct fm_cqi));
    711                         memcpy(&SortData[j-1], &swap, sizeof(struct fm_cqi));
    712                     }
    713                 }
    714                 LOGI("End sort \n");
    715                 break;
    716             }
    717         default:
    718             break;
    719     }
    720 
    721     ChannelNo = 0;
    722     for (i=0; i<Num; i++) {
    723         if (SortData[i].reserve == 1) {
    724             SortData[i].ch /= 10;
    725 
    726             scan_tbl[ChannelNo]=SortData[i].ch;
    727             ChannelNo++;
    728         }
    729     }
    730     *max_cnt=ChannelNo;
    731 
    732     LOGI("return channel no.[%d] \n", ChannelNo);
    733     return 0;
    734 }
    735 
    736 int FMR_scan(int idx, uint16_t *scan_tbl, int *max_cnt)
    737 {
    738     fm_s32 ret = 0;
    739     fm_s32 band_channel_no = 0;
    740     fm_u8 seek_space = 10;
    741     fm_u16 Start_Freq = 8750;
    742     fm_u8 NF_Space = 41;
    743 
    744     //FM radio seek space,5:50KHZ; 1:100KHZ; 2:200KHZ
    745     if (fmr_data.cfg_data.seek_space == 5) {
    746         seek_space = 5;
    747     } else if (fmr_data.cfg_data.seek_space == 2) {
    748         seek_space = 20;
    749     } else {
    750         seek_space = 10;
    751     }
    752     if (fmr_data.cfg_data.band == FM_BAND_JAPAN)/* Japan band      76MHz ~ 90MHz */ {
    753         band_channel_no = (9600-7600)/seek_space + 1;
    754         Start_Freq = 7600;
    755         NF_Space = 400/seek_space;
    756     } else if (fmr_data.cfg_data.band == FM_BAND_JAPANW)/* Japan wideband  76MHZ ~ 108MHz */ {
    757         band_channel_no = (10800-7600)/seek_space + 1;
    758         Start_Freq = 7600;
    759         NF_Space = 640/seek_space;
    760     } else/* US/Europe band  87.5MHz ~ 108MHz (DEFAULT) */ {
    761         band_channel_no = (10800-8750)/seek_space + 1;
    762         Start_Freq = 8750;
    763         NF_Space = 410/seek_space;
    764     }
    765 
    766     ret = FMR_scan_Channels(idx, scan_tbl, max_cnt, band_channel_no, Start_Freq, seek_space, NF_Space);
    767 
    768     return ret;
    769 }
    770 
    771 int FMR_stop_scan(int idx)
    772 {
    773     fmr_data.scan_stop = fm_true;
    774     return 0;
    775 }
    776 
    777 int FMR_turn_on_off_rds(int idx, int onoff)
    778 {
    779     int ret = 0;
    780 
    781     FMR_ASSERT(FMR_cbk_tbl(idx).turn_on_off_rds)
    782     ret = FMR_cbk_tbl(idx).turn_on_off_rds(FMR_fd(idx), onoff);
    783     if (ret) {
    784         LOGE("%s, failed\n", __func__);
    785     }
    786     LOGD("%s, [onoff=%d] [ret=%d]\n", __func__, onoff, ret);
    787     return ret;
    788 }
    789 
    790 int FMR_read_rds_data(int idx, uint16_t *rds_status)
    791 {
    792     int ret = 0;
    793 
    794     FMR_ASSERT(FMR_cbk_tbl(idx).read_rds_data);
    795     FMR_ASSERT(rds_status);
    796 
    797     ret = FMR_cbk_tbl(idx).read_rds_data(FMR_fd(idx), &fmr_data.rds, rds_status);
    798     /*if (ret) {
    799         LOGE("%s, get no event\n", __func__);
    800     }*/
    801     LOGD("%s, [status=%d] [ret=%d]\n", __func__, *rds_status, ret);
    802     return ret;
    803 }
    804 
    805 int FMR_active_af(int idx, uint16_t *ret_freq)
    806 {
    807     int ret = 0;
    808 
    809     FMR_ASSERT(FMR_cbk_tbl(idx).active_af);
    810     FMR_ASSERT(ret_freq);
    811     ret = FMR_cbk_tbl(idx).active_af(FMR_fd(idx),
    812                                     &fmr_data.rds,
    813                                     fmr_data.cfg_data.band,
    814                                     fmr_data.cur_freq,
    815                                     ret_freq);
    816     if ((ret == 0) && (*ret_freq != fmr_data.cur_freq)) {
    817         fmr_data.cur_freq = *ret_freq;
    818         LOGI("active AF OK, new channel[freq=%d]\n", fmr_data.cur_freq);
    819     }
    820     LOGD("%s, [ret=%d]\n", __func__, ret);
    821     return ret;
    822 }
    823 
    824 int FMR_ana_switch(int idx, int antenna)
    825 {
    826     int ret = 0;
    827 
    828     FMR_ASSERT(FMR_cbk_tbl(idx).ana_switch);
    829 
    830     if (fmr_data.cfg_data.short_ana_sup == true) {
    831         ret = FMR_cbk_tbl(idx).ana_switch(FMR_fd(idx), antenna);
    832         if (ret) {
    833             LOGE("%s failed, [ret=%d]\n", __func__, ret);
    834         }
    835     } else {
    836         LOGW("FM antenna switch not support!\n");
    837         ret = -ERR_UNSUPT_SHORTANA;
    838     }
    839 
    840     LOGD("%s, [ret=%d]\n", __func__, ret);
    841     return ret;
    842 }
    843 
    844