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