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