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
40struct fmr_ds fmr_data;
41struct 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
53int 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
83int FMR_chk_cfg_data(int idx)
84{
85    //TODO Need check? how to check?
86    return 0;
87}
88
89static void sig_alarm(int sig)
90{
91    LOGI("+++Receive sig %d\n", sig);
92    return;
93}
94
95int 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
140fail:
141    pfmr_data[idx] = NULL;
142
143    return -1;
144}
145
146int 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
171int 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
181int 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
202int 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
212int 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
228int 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
240int 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
253int 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*/
269fm_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
280fm_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*/
302fm_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
322return fm_true : need check cur_freq->valid
323         fm_false: check faild, should stop seek
324*/
325static 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/*
355check more 2 freq, curfreq: current freq, seek_dir: 1,forward. 0,backword
356*/
357static 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
391return -1 : seek fail
392         0: seek success
393*/
394int 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
487int 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
531int 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
549int 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
565int 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
574int 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
581int 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
736int 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
771int FMR_stop_scan(int idx)
772{
773    fmr_data.scan_stop = fm_true;
774    return 0;
775}
776
777int 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
790int 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
805int 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
824int 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