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 
FMR_get_cfgs(int idx)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 
FMR_chk_cfg_data(int idx)83 int FMR_chk_cfg_data(int idx)
84 {
85     //TODO Need check? how to check?
86     return 0;
87 }
88 
sig_alarm(int sig)89 static void sig_alarm(int sig)
90 {
91     LOGI("+++Receive sig %d\n", sig);
92     return;
93 }
94 
FMR_init()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 
FMR_open_dev(int idx)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 
FMR_close_dev(int idx)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 
FMR_pwr_up(int idx,int freq)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 
FMR_pwr_down(int idx,int type)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 
FMR_get_chip_id(int idx,int * chipid)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 
FMR_get_ps(int idx,uint8_t ** ps,int * ps_len)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 
FMR_get_rt(int idx,uint8_t ** rt,int * rt_len)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 
FMR_tune(int idx,int freq)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*/
FMR_DensenseDetect(fm_s32 idx,fm_u16 ChannelNo,fm_s32 RSSI)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 
FMR_SevereDensense(fm_u16 ChannelNo,fm_s32 RSSI)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*/
FMR_NoiseFloorDetect(fm_bool * rF,fm_s32 rssi,fm_s32 * F_rssi)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 */
FMR_Seek_TuneCheck(int idx,fm_softmute_tune_t * cur_freq)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 */
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)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 */
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)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 
FMR_seek(int idx,int start_freq,int dir,int * ret_freq)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 
FMR_set_mute(int idx,int mute)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 
FMR_is_rdsrx_support(int idx,int * supt)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 
FMR_Pre_Search(int idx)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 
FMR_Restore_Search(int idx)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 
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)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 
FMR_scan(int idx,uint16_t * scan_tbl,int * max_cnt)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 
FMR_stop_scan(int idx)771 int FMR_stop_scan(int idx)
772 {
773     fmr_data.scan_stop = fm_true;
774     return 0;
775 }
776 
FMR_turn_on_off_rds(int idx,int onoff)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 
FMR_read_rds_data(int idx,uint16_t * rds_status)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 
FMR_active_af(int idx,uint16_t * ret_freq)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 
FMR_ana_switch(int idx,int antenna)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