blob: 55bcef43d783654ec998840888c293eb6d46db11 [file] [log] [blame]
Venkateshwarlu Domakondaacdd9a42015-03-24 10:28:37 +05301/*
2Copyright (c) 2015, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30#include <cstdio>
31#include <cstdlib>
32#include <cstring>
33#include <fcntl.h>
34#include <utils/Log.h>
35#include <cutils/properties.h>
36#include <sys/ioctl.h>
37#include <math.h>
38#include "FmRadioController.h"
39#include "FmIoctlsInterface.h"
40#include "ConfigFmThs.h"
41#include <linux/videodev2.h>
42
43//Reset all variables to default value
44static FmIoctlsInterface * FmIoct;
45FmRadioController :: FmRadioController
46(
47)
48{
49 cur_fm_state = FM_OFF;
50 prev_freq = -1;
51 seek_scan_canceled = false;
52 af_enabled = 0;
53 rds_enabled = 0;
54 event_listener_canceled = false;
55 is_rds_support = false;
56 is_ps_event_received = false;
57 is_rt_event_received = false;
58 is_af_jump_received = false;
59 mutex_fm_state = PTHREAD_MUTEX_INITIALIZER;
60 mutex_seek_compl_cond = PTHREAD_MUTEX_INITIALIZER;
61 mutex_scan_compl_cond = PTHREAD_MUTEX_INITIALIZER;
62 mutex_tune_compl_cond = PTHREAD_MUTEX_INITIALIZER;
63 mutex_turn_on_cond = PTHREAD_MUTEX_INITIALIZER;
64 turn_on_cond = PTHREAD_COND_INITIALIZER;
65 seek_compl_cond = PTHREAD_COND_INITIALIZER;
66 scan_compl_cond = PTHREAD_COND_INITIALIZER;
67 tune_compl_cond = PTHREAD_COND_INITIALIZER;
68 event_listener_thread = 0;
69 fd_driver = -1;
70 FmIoct = new FmIoctlsInterface();
71}
72
73/* Turn off FM */
74FmRadioController :: ~FmRadioController
75(
76)
77{
78 if((cur_fm_state != FM_OFF)) {
79 Stop_Scan_Seek();
80 set_fm_state(FM_OFF_IN_PROGRESS);
81 FmIoctlsInterface::set_control(fd_driver,
82 V4L2_CID_PRV_STATE, FM_DEV_NONE);
83 }
84 if(event_listener_thread != 0) {
85 event_listener_canceled = true;
86 pthread_join(event_listener_thread, NULL);
87 }
88}
89
90int FmRadioController ::open_dev()
91{
92 int ret = FM_SUCCESS;
93
94 fd_driver = open(FM_DEVICE_PATH, O_RDONLY, O_NONBLOCK);
95
96 if (fd_driver < 0) {
97 ALOGE("%s failed, [fd=%d] %s\n", __func__, fd_driver, FM_DEVICE_PATH);
98 return FM_FAILURE;
99 }
100
101 ALOGD("%s, [fd=%d] \n", __func__, fd_driver);
102 return ret;
103}
104
105int FmRadioController ::close_dev()
106{
107 int ret = 0;
108
109 if (fd_driver > 0) {
110 close(fd_driver);
111 fd_driver = -1;
112 }
113 ALOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd_driver, ret);
114 return ret;
115}
116
117struct timespec FmRadioController :: set_time_out
118(
119 int secs
120)
121{
122 struct timespec ts;
123 struct timeval tp;
124
125 gettimeofday(&tp, NULL);
126 ts.tv_sec = tp.tv_sec;
127 ts.tv_nsec = tp.tv_usec * 1000;
128 ts.tv_sec += secs;
129
130 return ts;
131}
132
133//Get current tuned frequency
134//Return -1 if failed to get freq
135long FmRadioController :: GetChannel
136(
137 void
138)
139{
140 long freq = -1;
141 int ret;
142
143 if((cur_fm_state != FM_OFF) &&
144 (cur_fm_state != FM_ON_IN_PROGRESS)) {
145 ret = FmIoctlsInterface::get_cur_freq(fd_driver, freq);
146 if(ret == FM_SUCCESS) {
147 ALOGI("FM get freq is successfull, freq is: %ld\n", freq);
148 }else {
149 ALOGE("FM get frequency failed, freq is: %ld\n", freq);
150 }
151 }else {
152 ALOGE("FM get freq is not valid in current state\n");
153 }
154 return freq;
155}
156
157int FmRadioController ::Pwr_Up(int freq)
158{
159 int ret = FM_SUCCESS;
160 struct timespec ts;
161 ConfigFmThs thsObj;
162
163 ALOGI("%s,[freq=%d]\n", __func__, freq);
164 if (fd_driver < 0) {
165 ret = open_dev();
166 if (ret != FM_SUCCESS) {
167 ALOGE("Dev open failed\n");
168 return FM_FAILURE;
169 }
170 }
171
172 if (cur_fm_state == FM_OFF) {
173 ALOGE("cur_fm_state = %d\n",cur_fm_state);
174 ret = FmIoctlsInterface::start_fm_patch_dl(fd_driver);
175 if (ret != FM_SUCCESS) {
176 ALOGE("FM patch downloader failed: %d\n", ret);
177 close_dev();
178 set_fm_state(FM_OFF);
179 return FM_FAILURE;
180 }
181 if (event_listener_thread == 0) {
182 ret = pthread_create(&event_listener_thread, NULL,
183 handle_events, this);
184 if (ret == 0) {
185 ALOGI("Lock the mutex for FM turn on cond\n");
186 pthread_mutex_lock(&mutex_turn_on_cond);
187 ts = set_time_out(READY_EVENT_TIMEOUT);
188 ret = FmIoctlsInterface::set_control(fd_driver,
189 V4L2_CID_PRV_STATE, FM_RX);
190 if (ret == FM_SUCCESS) {
191 ALOGI("Waiting for timedout or FM on\n");
192 pthread_cond_timedwait(&turn_on_cond,
193 &mutex_turn_on_cond, &ts);
194 ALOGI("Unlocked mutex & timedout or condition satisfied\n");
195 pthread_mutex_unlock(&mutex_turn_on_cond);
196 if (cur_fm_state == FM_ON) {//after READY event
197 ret = SetBand(BAND_87500_108000);
198 if (ret != FM_SUCCESS) {
199 ALOGE("set band failed\n");
200 ret = FM_FAILURE;
201 goto exit;
202 }
203 ret = SetChannelSpacing(CHAN_SPACE_100);
204 if (ret != FM_SUCCESS) {
205 ALOGE("set channel spacing failed\n");
206 ret = FM_FAILURE;
207 goto exit;
208 }
209 ret = SetDeConstant(DE_EMP50);
210 if (ret != FM_SUCCESS) {
211 ALOGE("set Emphasis failed\n");
212 ret = FM_FAILURE;
213 goto exit;
214 }
215 thsObj.SetRxSearchAfThs(FM_PERFORMANCE_PARAMS, fd_driver);
216 SetStereo();
217 ret = TuneChannel(freq);
218 if (ret != FM_SUCCESS) {
219 ALOGI("FM set freq command failed\n");
220 ret = FM_FAILURE;
221 goto exit;
222 }
223 return FM_SUCCESS;
224 } else { //if time out
225 ret = FM_FAILURE;
226 goto exit;
227 }
228 } else {
229 ALOGE("Set FM on control failed\n");
230 pthread_mutex_unlock(&mutex_turn_on_cond);
231 ALOGI("Unlocked the FM on cond mutex\n");
232 ret = FM_FAILURE;
233 goto close_fd;
234 }
235 } else {
236 ALOGE("FM event listener thread failed: %d\n", ret);
237 set_fm_state(FM_OFF);
238 return FM_FAILURE;
239 }
240 } else {
241 ALOGE("FM event listener threadi existed\n");
242 return FM_SUCCESS;
243 }
244 } else if(cur_fm_state != FM_ON_IN_PROGRESS) {
245 return FM_SUCCESS;
246 } else {
247 return FM_FAILURE;
248 }
249
250exit:
251 FmIoctlsInterface::set_control(fd_driver,
252 V4L2_CID_PRV_STATE, FM_DEV_NONE);
253close_fd:
254 event_listener_canceled = true;
255 pthread_join(event_listener_thread, NULL);
256 close(fd_driver);
257 fd_driver = -1;
258 set_fm_state(FM_OFF);
259
260 ALOGD("%s, [ret=%d]\n", __func__, ret);
261 return ret;
262}
263
264int FmRadioController ::Pwr_Down()
265{
266 int ret = 0;
267
268 if((cur_fm_state != FM_OFF)) {
269 Stop_Scan_Seek();
270 set_fm_state(FM_OFF_IN_PROGRESS);
271 FmIoctlsInterface::set_control(fd_driver,
272 V4L2_CID_PRV_STATE, FM_DEV_NONE);
273 }
274 if(event_listener_thread != 0) {
275 ALOGD("%s, event_listener_thread canceeled\n", __func__);
276 event_listener_canceled = true;
277 pthread_join(event_listener_thread, NULL);
278 }
279 ALOGD("%s, [ret=%d]\n", __func__, ret);
280 return ret;
281}
282//Tune to a Freq
283//Return FM_SUCCESS on success FM_FAILURE
284//on failure
285int FmRadioController :: TuneChannel
286(
287 long freq
288)
289{
290 int ret = FM_SUCCESS;
291 struct timespec ts;
292
293 if((cur_fm_state == FM_ON) &&
294 (freq > 0)) {
295 set_fm_state(FM_TUNE_IN_PROGRESS);
296 ret = FmIoctlsInterface::set_freq(fd_driver,
297 freq);
298 if(ret == FM_SUCCESS) {
299 ALOGI("FM set frequency command set successfully\n");
300 pthread_mutex_lock(&mutex_tune_compl_cond);
301 ts = set_time_out(TUNE_EVENT_TIMEOUT);
302 ret = pthread_cond_timedwait(&tune_compl_cond, &mutex_tune_compl_cond, &ts);
303 pthread_mutex_unlock(&mutex_tune_compl_cond);
304 }else {
305 if((cur_fm_state != FM_OFF)) {
306 set_fm_state(FM_ON);
307 }
308 ALOGE("FM set freq command failed\n");
309 }
310 }else {
311 ALOGE("Fm is not in proper state for tuning to a freq\n");
312 ret = FM_FAILURE;
313 }
314 return ret;
315}
316
317int FmRadioController :: Seek(int dir)
318{
319 int ret = 0;
320 int freq = -1;
321 struct timespec ts;
322
323 if (cur_fm_state != FM_ON) {
324 ALOGE("%s error Fm state: %d\n", __func__,cur_fm_state);
325 return FM_FAILURE;
326 }
327
328 ALOGI("FM seek started\n");
329 set_fm_state(SEEK_IN_PROGRESS);
330 ret = FmIoctlsInterface::set_control(fd_driver,
331 V4L2_CID_PRV_SRCHMODE, SEEK_MODE);
332 if (ret != FM_SUCCESS) {
333 set_fm_state(FM_ON);
334 return FM_FAILURE;
335 }
336
337 ret = FmIoctlsInterface::set_control(fd_driver,
338 V4L2_CID_PRV_SCANDWELL, SEEK_DWELL_TIME);
339 if (ret != FM_SUCCESS) {
340 set_fm_state(FM_ON);
341 return FM_FAILURE;
342 }
343
344 if (dir == 1) {
345 ret = FmIoctlsInterface::start_search(fd_driver,
346 SEARCH_UP);
347 } else {
348 ret = FmIoctlsInterface::start_search(fd_driver,
349 SEARCH_DOWN);
350 }
351
352 if (ret != FM_SUCCESS) {
353 set_fm_state(FM_ON);
354 return FM_FAILURE;
355 }
356 pthread_mutex_lock(&mutex_seek_compl_cond);
357 ts = set_time_out(SEEK_COMPL_TIMEOUT);
358 ret = pthread_cond_timedwait(&seek_compl_cond, &mutex_seek_compl_cond, &ts);
359 pthread_mutex_unlock(&mutex_seek_compl_cond);
360 if ((cur_fm_state != SEEK_IN_PROGRESS) && !seek_scan_canceled) {
361 ALOGI("Seek completed without timeout\n");
362 freq = GetChannel();
363 }
364 seek_scan_canceled = false;
365 return freq;
366}
367
368bool FmRadioController ::IsRds_support
369(
370 void
371)
372{
373 is_rds_support = true;
374 ALOGI("is_rds_support: \n", is_rds_support);
375 return is_rds_support;
376}
377
378//HardMute both audio channels
379int FmRadioController ::MuteOn()
380{
381 int ret;
382
383 ALOGE("cur_fm_state = %d\n", cur_fm_state);
384 if((cur_fm_state != FM_OFF) &&
385 (cur_fm_state != FM_ON_IN_PROGRESS)) {
386 ret = FmIoctlsInterface::set_control(fd_driver,
387 V4L2_CID_AUDIO_MUTE, MUTE_L_R_CHAN);
388 ALOGE("CMD executed mute\n");
389 }else {
390 ret = FM_FAILURE;
391 }
392 return ret;
393}
394
395//Unmute both audio channel
396int FmRadioController ::MuteOff()
397{
398 int ret;
399
400 ALOGE("cur_fm_state = %d\n", cur_fm_state);
401 if((cur_fm_state != FM_OFF) &&
402 (cur_fm_state != FM_ON_IN_PROGRESS)) {
403 ret = FmIoctlsInterface::set_control(fd_driver,
404 V4L2_CID_AUDIO_MUTE, UNMUTE_L_R_CHAN);
405 ALOGE("CMD executed for unmute\n");
406 }else {
407 ret = FM_FAILURE;
408 }
409 return ret;
410}
411
412//
413int FmRadioController ::SetSoftMute(bool mode)
414{
415 int ret;
416
417 if((cur_fm_state != FM_OFF) &&
418 (cur_fm_state != FM_ON_IN_PROGRESS)) {
419 ret = FmIoctlsInterface::set_control(fd_driver,
420 V4L2_CID_PRV_SOFT_MUTE, mode);
421 }else {
422 ret = FM_FAILURE;
423 }
424 return ret;
425}
426
427int FmRadioController :: Set_mute(bool mute)
428{
429 int ret = 0;
430
431 if (mute) {
432 ret = MuteOn();
433 } else {
434 ret = MuteOff();
435 }
436
437 if (ret)
438 ALOGE("%s failed, %d\n", __func__, ret);
439 ALOGD("%s, [mute=%d] [ret=%d]\n", __func__, mute, ret);
440 return ret;
441}
442
443int FmRadioController :: Stop_Scan_Seek
444(
445)
446{
447 int ret;
448
449 if((cur_fm_state == SEEK_IN_PROGRESS) ||
450 (cur_fm_state == SCAN_IN_PROGRESS)) {
451 ret = FmIoctlsInterface::set_control(fd_driver,
452 V4L2_CID_PRV_SRCHON, 0);
453 if (ret == FM_SUCCESS) {
454 ALOGI("FM Seek cancel command set successfully\n");
455 seek_scan_canceled = true;
456 } else {
457 ALOGE("FM Seek cancel command sent failed\n");
458 }
459 } else {
460 ALOGE("FM is not in proper state for cancelling Seek operation\n");
461 ret = FM_FAILURE;
462 }
463 return ret;
464}
465
466int FmRadioController :: ReadRDS() //todo define each RDS flag
467{
468 int ret = 0;
469
470 if (is_ps_event_received)
471 ret |= RDS_EVT_PS_UPDATE;
472 if (is_rt_event_received)
473 ret |= RDS_EVT_RT_UPDATE;
474 if (is_af_jump_received)
475 ret |= RDS_EVT_AF_JUMP;
476
477 return ret;
478}
479
480int FmRadioController :: Get_ps(char *ps, int *ps_len)
481{
482 int ret = 0;
483 int len = 0;
484 char raw_rds[STD_BUF_SIZE];
485
486 ret = FmIoctlsInterface::get_buffer(fd_driver,
487 raw_rds, STD_BUF_SIZE, PS_IND);
488 if (ret <= 0) {
489 return FM_FAILURE;
490 } else {
491 if (raw_rds[PS_STR_NUM_IND] > 0) {
492 if (ps != NULL) {
493 for(int i = 0; i < MAX_PS_LEN; i++) {
494 ps[i] = raw_rds[PS_DATA_OFFSET_IND + i];
495 if (ps[i] == 0) {
496 break;
497 } else if((ps[len] <= LAST_CTRL_CHAR) ||
498 (ps[len] >= FIRST_NON_PRNT_CHAR)) {
499 ps[i] = SPACE_CHAR;
500 continue;
501 }
502 len++;
503 }
504 if (len < (MAX_PS_LEN - 1)) {
505 ps[len] = '\0';
506 *ps_len = len + 1;
507 } else {
508 *ps_len = len;
509 }
510 ALOGI("PS is: %s\n", ps);
511 } else {
512 return FM_FAILURE;
513 }
514 }
515 }
516 is_ps_event_received = false;
517 ALOGD("%s, [ps_len=%d]\n", __func__, *ps_len);
518 return FM_SUCCESS;
519}
520
521int FmRadioController :: Get_rt(char *rt, int *rt_len)
522{
523 int ret = 0;
524 int len = 0;
525 char raw_rds[STD_BUF_SIZE];
526
527 ret = FmIoctlsInterface::get_buffer(fd_driver,
528 raw_rds, STD_BUF_SIZE, RT_IND);
529 if (ret <= 0) {
530 return FM_FAILURE;
531 } else {
532 if (rt != NULL) {
533 if ((raw_rds[RT_LEN_IND] > 0) &&
534 (raw_rds[RT_LEN_IND] <= MAX_RT_LEN)) {
535 for(len = 0; len < raw_rds[RT_LEN_IND]; len++) {
536 rt[len] = raw_rds[RT_DATA_OFFSET_IND + len];
537 ALOGI("Rt byte[%d]: %d\n", len, rt[len]);
538 if ((rt[len] <= LAST_CTRL_CHAR) ||
539 (rt[len] >= FIRST_NON_PRNT_CHAR)) {
540 rt[len] = SPACE_CHAR;
541 continue;
542 }
543 }
544 if (len < (MAX_RT_LEN - 1)) {
545 rt[len] = '\0';
546 *rt_len = len + 1;
547 } else {
548 *rt_len = len;
549 }
550 ALOGI("Rt is: %s\n", rt);
551 ALOGI("RT text A / B: %d\n", raw_rds[RT_A_B_FLAG_IND]);
552 } else {
553 return FM_FAILURE;
554 }
555 } else {
556 return FM_FAILURE;
557 }
558 }
559 is_rt_event_received = false;
560 ALOGD("%s, [rt_len=%d]\n", __func__, *rt_len);
561 return FM_SUCCESS;
562}
563
564int FmRadioController :: Get_AF_freq(uint16_t *ret_freq)
565{
566 int ret =0;
567 ULINT lowBand, highBand;
568 float real_freq = 0;
569
570 ALOGI("get_AF_freq\n");
571 ret = FmIoctlsInterface::get_lowerband_limit(fd_driver,
572 lowBand);
573 if (ret != FM_SUCCESS) {
574 ALOGE("failed to get lowerband: %d\n", ret);
575 return FM_FAILURE;
576 }
577 ALOGI("lowBand = %ld\n",lowBand);
578 ret = FmIoctlsInterface::get_upperband_limit(fd_driver,
579 highBand);
580 if (ret != FM_SUCCESS) {
581 ALOGE("failed to getgherband: %d\n", ret);
582 return FM_FAILURE;
583 }
584 ALOGI("highBand = %ld\n",highBand);
585 real_freq = GetChannel();
586 if ((real_freq < lowBand ) || (real_freq > highBand)) {
587 ALOGE("AF freq is not in band limits\ni");
588 return FM_FAILURE;
589 } else {
590 *ret_freq = real_freq/100;
591 }
592 is_af_jump_received = false;
593 return FM_SUCCESS;
594}
595
596//Emphasis:
597//75microsec: 0, 50 microsec: 1
598//return FM_SUCCESS on success, FM_FAILURE
599//on failure
600int FmRadioController :: SetDeConstant
601(
602 long emphasis
603)
604{
605 int ret;
606
607 ALOGE("cur_fm_state: %d, emphasis: %d\n", cur_fm_state, emphasis);
608 if(cur_fm_state == FM_ON) {
609 switch(emphasis) {
610 case DE_EMP75:
611 case DE_EMP50:
612 ret = FmIoctlsInterface::set_control(fd_driver,
613 V4L2_CID_PRV_EMPHASIS, emphasis);
614 break;
615 default:
616 ALOGE("FM value pass for set Deconstant is invalid\n");
617 ret = FM_FAILURE;
618 break;
619 }
620 }else {
621 ALOGE("FM is not in proper state to set De constant\n");
622 ret = FM_FAILURE;
623 }
624 return ret;
625}
626
627int FmRadioController :: GetStationList
628(
629 uint16_t *scan_tbl, int *max_cnt
630)
631{
632 char srch_list[STD_BUF_SIZE];
633 int ret;
634 ULINT lowBand, highBand;
635 int station_num = 0;
636 int stationList[FM_RX_SRCHLIST_MAX_STATIONS];
637 int tmpFreqByte1=0;
638 int tmpFreqByte2=0;
639 int freq = 0;
640 float real_freq = 0;
641 int i = 0, j = 0;
642
643 ALOGI("getstationList\n");
644 ret = FmIoctlsInterface::get_lowerband_limit(fd_driver,
645 lowBand);
646 if (ret != FM_SUCCESS) {
647 ALOGE("failed to get lowerband: %d\n", ret);
648 return FM_FAILURE;
649 }
650 ALOGI("lowBand = %ld\n",lowBand);
651 ret = FmIoctlsInterface::get_upperband_limit(fd_driver,
652 highBand);
653 if (ret != FM_SUCCESS) {
654 ALOGE("failed to getgherband: %d\n", ret);
655 return FM_FAILURE;
656 }
657 ALOGI("highBand = %ld\n",highBand);
658 ret = FmIoctlsInterface::get_buffer(fd_driver,
659 srch_list, STD_BUF_SIZE, STATION_LIST_IND);
660 if ((int)srch_list[0] >0) {
661 station_num = (int)srch_list[0];
662 }
663 ALOGI("station_num: %d ", station_num);
664 *max_cnt = station_num;
665 for (i=0;i<station_num;i++) {
666 freq = 0;
667 ALOGI(" Byte1 = %d", srch_list[i * NO_OF_BYTES_EACH_FREQ + 1]);
668 ALOGI(" Byte2 = %d", srch_list[i * NO_OF_BYTES_EACH_FREQ + 2]);
669 tmpFreqByte1 = srch_list[i * NO_OF_BYTES_EACH_FREQ + 1] & 0xFF;
670 tmpFreqByte2 = srch_list[i * NO_OF_BYTES_EACH_FREQ + 2] & 0xFF;
671 ALOGI(" tmpFreqByte1 = %d", tmpFreqByte1);
672 ALOGI(" tmpFreqByte2 = %d", tmpFreqByte2);
673 freq = (tmpFreqByte1 & EXTRACT_FIRST_BYTE) << 8;
674 freq |= tmpFreqByte2;
675 ALOGI(" freq: %d", freq);
676 real_freq = (freq * FREQ_MULTIPLEX) + lowBand;
677 ALOGI(" real_freq: %d", real_freq);
678 if ( (real_freq < lowBand ) || (real_freq > highBand) ) {
679 ALOGI("Frequency out of band limits");
680 } else {
681 scan_tbl[j] = (real_freq/SRCH_DIV);
682 ALOGI(" scan_tbl: %d", scan_tbl[j]);
683 j++;
684 }
685 }
686 return FM_SUCCESS;
687}
688
689int FmRadioController ::ScanList
690(
691 uint16_t *scan_tbl, int *max_cnt
692)
693{
694 int ret;
695 struct timespec ts;
696
697 /* Check current state of FM device */
698 if (cur_fm_state == FM_ON) {
699 ALOGI("FM searchlist started\n");
700 set_fm_state(SCAN_IN_PROGRESS);
701 ret = FmIoctlsInterface::set_control(fd_driver,
702 V4L2_CID_PRV_SRCHMODE, SRCHLIST_MODE_STRONG);
703 if (ret != FM_SUCCESS) {
704 set_fm_state(FM_ON);
705 return FM_FAILURE;
706 }
707 ret = FmIoctlsInterface::set_control(fd_driver,
708 V4L2_CID_PRV_SRCH_CNT, FM_RX_SRCHLIST_MAX_STATIONS);
709 if (ret != FM_SUCCESS) {
710 set_fm_state(FM_ON);
711 return FM_FAILURE;
712 }
713 ret = FmIoctlsInterface::start_search(fd_driver,
714 SEARCH_UP);
715 if (ret != FM_SUCCESS) {
716 set_fm_state(FM_ON);
717 return FM_FAILURE;
718 }
719 pthread_mutex_lock(&mutex_scan_compl_cond);
720 ts = set_time_out(SCAN_COMPL_TIMEOUT);
721 ALOGI("Wait for Scan Timeout or scan complete");
722 ret = pthread_cond_timedwait(&scan_compl_cond, &mutex_scan_compl_cond, &ts);
723 ALOGI("Scan complete or timedout");
724 pthread_mutex_unlock(&mutex_scan_compl_cond);
725 if (cur_fm_state == FM_ON && !seek_scan_canceled) {
726 GetStationList(scan_tbl, max_cnt);
727 } else {
728 seek_scan_canceled = false;
729 return FM_FAILURE;
730 }
731 } else {
732 ALOGI("Scanlist: not proper state %d\n",cur_fm_state );
733 return FM_FAILURE;
734 }
735 return FM_SUCCESS;
736}
737
738long FmRadioController :: GetCurrentRSSI
739(
740 void
741)
742{
743 int ret;
744 long rmssi = -129;
745
746 if((cur_fm_state != FM_OFF) &&
747 (cur_fm_state != FM_ON_IN_PROGRESS)) {
748 ret = FmIoctlsInterface::get_rmssi(fd_driver, rmssi);
749 }else {
750 }
751 return rmssi;
752}
753
754//enable, disable value to receive data of a RDS group
755//return FM_SUCCESS on success, FM_FAILURE on failure
756int FmRadioController :: SetRdsGrpProcessing
757(
758 int grps
759)
760{
761 int ret;
762 long mask;
763
764 if(cur_fm_state == FM_ON) {
765 ret = FmIoctlsInterface::get_control(fd_driver,
766 V4L2_CID_PRV_RDSGROUP_PROC, mask);
767 if(ret != FM_SUCCESS) {
768 return ret;
769 }
770 mask &= 0xC7;
771 mask |= ((grps & 0x07) << 3);
772 ret = FmIoctlsInterface::set_control(fd_driver,
773 V4L2_CID_PRV_RDSGROUP_PROC, (int)mask);
774 }else {
775 ret = FM_FAILURE;
776 }
777 return ret;
778}
779
780//Enable RDS data receiving
781//Enable RT, PS, AF Jump, RTPLUS, ERT etc
782int FmRadioController :: EnableRDS
783(
784 void
785)
786{
787 int ret = FM_FAILURE;
788
789 ALOGE("%s:cur_fm_state = %d\n", __func__, cur_fm_state);
790 if (cur_fm_state == FM_ON) {
791 ret = FmIoctlsInterface::set_control(fd_driver,
792 V4L2_CID_PRV_RDSON, 1);
793 if (ret != FM_SUCCESS) {
794 ALOGE("RDS ON failed\n");
795 return ret;
796 }
797 ret = SetRdsGrpProcessing(FM_RX_RDS_GRP_RT_EBL |
798 FM_RX_RDS_GRP_PS_EBL |
799 FM_RX_RDS_GRP_AF_EBL |
800 FM_RX_RDS_GRP_PS_SIMPLE_EBL);
801 if (ret != FM_SUCCESS) {
802 ALOGE("Set RDS grp processing\n");
803 return ret;
804 }
805 ret = FM_SUCCESS;
806 rds_enabled = 1;
807 EnableAF();
808 } else {
809 ALOGE("%s:not in proper state cur_fm_state = %d\n", cur_fm_state);
810 return ret;
811 }
812 return ret;
813}
814
815//Disable all RDS data processing
816//RT, ERT, RT PLUS, PS
817int FmRadioController :: DisableRDS
818(
819 void
820)
821{
822 int ret = FM_FAILURE;
823
824 ALOGE("%s:cur_fm_state = %d\n", __func__, cur_fm_state);
825 if (cur_fm_state == FM_ON) {
826 ret = FmIoctlsInterface::set_control(fd_driver,
827 V4L2_CID_PRV_RDSON, 2);
828 if (ret != FM_SUCCESS) {
829 ALOGE("Disable RDS failed\n");
830 return ret;
831 }
832 ret = FM_SUCCESS;
833 rds_enabled = 0;
834 DisableAF();
835 } else {
836 ALOGE("%s:not in proper state cur_fm_state = %d\n", cur_fm_state);
837 ret = FM_FAILURE;
838 }
839 return ret;
840}
841
842int FmRadioController :: Turn_On_Off_Rds(bool onoff)
843{
844 int ret = 0;
845
846 if (onoff) {
847 ret = EnableRDS();
848 } else {
849 ret = DisableRDS();
850 }
851
852 if (ret) {
853 ALOGE("%s, failed\n", __func__);
854 }
855 ALOGD("%s, [onoff=%d] [ret=%d]\n", __func__, onoff, ret);
856 return ret;
857}
858
859//Enables Alternate Frequency switching
860int FmRadioController :: EnableAF
861(
862 void
863)
864{
865 int ret;
866 long rdsgrps;
867
868 if(cur_fm_state == FM_ON) {
869 ret = FmIoctlsInterface::get_control(fd_driver,
870 V4L2_CID_PRV_RDSGROUP_PROC, rdsgrps);
871 ret = FmIoctlsInterface::set_control(fd_driver,
872 V4L2_CID_PRV_RDSON, 1);
873 if(ret == FM_SUCCESS) {
874 ret = FmIoctlsInterface::set_control(fd_driver,
875 V4L2_CID_PRV_AF_JUMP, 1);
876 if(ret == FM_SUCCESS) {
877 af_enabled = 1;
878 }
879 } else {
880 }
881 } else {
882 ret = FM_FAILURE;
883 }
884 return ret;
885}
886
887//Disables Alternate Frequency switching
888int FmRadioController :: DisableAF
889(
890 void
891)
892{
893 int ret;
894 long rdsgrps;
895
896 if(cur_fm_state == FM_ON) {
897 ret = FmIoctlsInterface::get_control(fd_driver,
898 V4L2_CID_PRV_RDSGROUP_PROC, rdsgrps);
899 if(ret == FM_SUCCESS) {
900 ret = FmIoctlsInterface::set_control(fd_driver,
901 V4L2_CID_PRV_AF_JUMP, 0);
902 if(ret == FM_SUCCESS) {
903 af_enabled = 0;
904 }
905 }else {
906 }
907 }else {
908 ret = FM_FAILURE;
909 }
910 return ret;
911}
912
913//Set regional band
914int FmRadioController :: SetBand
915(
916 long band
917)
918{
919 int ret;
920
921 if(cur_fm_state == FM_ON) {
922 switch(band) {
923 case BAND_87500_108000:
924 ret = FmIoctlsInterface::set_band(fd_driver,
925 87500, 108000);
926 break;
927 case BAND_76000_108000:
928 ret = FmIoctlsInterface::set_band(fd_driver,
929 76000, 108000);
930 break;
931 case BAND_76000_90000:
932 ret = FmIoctlsInterface::set_band(fd_driver,
933 76000, 90000);
934 break;
935 default:
936 ALOGE("Band type: %ld is invalid\n", band);
937 ret = FM_FAILURE;
938 break;
939 }
940 }else {
941 ALOGE("FM is not in proper state to set band type\n");
942 ret = FM_FAILURE;
943 }
944 return ret;
945}
946
947//set spacing for successive channels
948int FmRadioController :: SetChannelSpacing
949(
950 long spacing
951)
952{
953 int ret;
954
955 if (cur_fm_state == FM_ON) {
956 ret = FmIoctlsInterface::set_control(fd_driver,
957 V4L2_CID_PRV_CHAN_SPACING, spacing);
958 } else {
959 ALOGE("FM is not in proper state to set the channel spacing\n");
960 ret = FM_FAILURE;
961 }
962 return ret;
963}
964
965int FmRadioController :: SetStereo
966(
967)
968{
969 int ret;
970
971 if((cur_fm_state != FM_OFF) &&
972 (cur_fm_state != FM_ON_IN_PROGRESS)) {
973 ret = FmIoctlsInterface::set_audio_mode(fd_driver,
974 STEREO);
975 }else {
976 ret = FM_FAILURE;
977 }
978 return ret;
979}
980
981int FmRadioController :: SetMono
982(
983)
984{
985 int ret;
986
987 if((cur_fm_state != FM_OFF) &&
988 (cur_fm_state != FM_ON_IN_PROGRESS)) {
989 ret = FmIoctlsInterface::set_audio_mode(fd_driver,
990 MONO);
991 }else {
992 ret = FM_FAILURE;
993 }
994 return ret;
995}
996
997bool FmRadioController :: GetSoftMute
998(
999)
1000{
1001 int ret = FM_SUCCESS;
1002 long mode = SMUTE_DISABLED;
1003
1004 if((cur_fm_state != FM_OFF) &&
1005 (cur_fm_state != FM_ON_IN_PROGRESS)) {
1006 ret = FmIoctlsInterface::get_control(fd_driver,
1007 V4L2_CID_PRV_SOFT_MUTE, mode);
1008 if(ret == FM_SUCCESS) {
1009 ALOGI("FM Get soft mute is successful: %ld\n", mode);
1010 }else {
1011 ALOGE("FM Get soft mute failed");
1012 }
1013 }else {
1014 ALOGE("FM is not in proper state for getting soft mute\n");
1015 ret = FM_FAILURE;
1016 }
1017 return mode;
1018}
1019
1020int FmRadioController :: Antenna_Switch(int antenna)
1021{
1022 int ret = 0;
1023
1024 if (antenna) {
1025 ret = FmIoctlsInterface::set_control(fd_driver,
1026 V4L2_CID_PRV_ANTENNA, 1);
1027 } else {
1028 ret = FmIoctlsInterface::set_control(fd_driver,
1029 V4L2_CID_PRV_ANTENNA, 0);
1030 }
1031 ALOGD("%s, antenna type = %d [ret=%d]\n", __func__, antenna, ret);
1032 return ret;
1033}
1034
1035int FmRadioController :: get_fm_state
1036(
1037)
1038{
1039 return cur_fm_state;
1040}
1041
1042void FmRadioController :: set_fm_state
1043(
1044 int state
1045)
1046{
1047 pthread_mutex_lock(&mutex_fm_state);
1048 cur_fm_state = state;
1049 pthread_mutex_unlock(&mutex_fm_state);
1050}
1051
1052void* FmRadioController :: handle_events
1053(
1054 void *arg
1055)
1056{
1057 int bytesread;
1058 char event_buff[STD_BUF_SIZE];
1059 bool status = true;
1060 FmRadioController *obj_p = static_cast<FmRadioController*>(arg);
1061
1062 while(status && !obj_p->event_listener_canceled) {
1063 bytesread = FmIoctlsInterface::get_buffer(obj_p->fd_driver,
1064 event_buff, STD_BUF_SIZE, EVENT_IND);
1065 for(int i = 0; i < bytesread; i++) {
1066 status = obj_p->process_radio_events(event_buff[i]);
1067 if(status == false) {
1068 break;
1069 }
1070 }
1071 }
1072 return NULL;
1073}
1074
1075int FmRadioController :: SetRdsGrpMask
1076(
1077 int mask
1078)
1079{
1080 int ret;
1081
1082 if((cur_fm_state != FM_OFF) &&
1083 (cur_fm_state != FM_OFF_IN_PROGRESS) &&
1084 (cur_fm_state != FM_ON_IN_PROGRESS)) {
1085 ret = FmIoctlsInterface::set_control(fd_driver,
1086 V4L2_CID_PRV_RDSGROUP_MASK, mask);
1087 }else {
1088 ret = FM_FAILURE;
1089 }
1090 return ret;
1091}
1092
1093void FmRadioController :: handle_enabled_event
1094(
1095 void
1096)
1097{
1098 ALOGI("FM handle ready Event\n");
1099 FmIoctlsInterface::set_control(fd_driver,
1100 V4L2_CID_PRV_AUDIO_PATH, AUDIO_DIGITAL_PATH);
1101 FmIoctlsInterface::set_calibration(fd_driver);
1102 pthread_mutex_lock(&mutex_turn_on_cond);
1103 set_fm_state(FM_ON);
1104 pthread_cond_broadcast(&turn_on_cond);
1105 pthread_mutex_unlock(&mutex_turn_on_cond);
1106}
1107
1108void FmRadioController :: handle_tuned_event
1109(
1110 void
1111)
1112{
1113 long freq = -1;
1114
1115 ALOGI("FM handle Tune event\n");
1116 freq = GetChannel();
1117 switch(cur_fm_state) {
1118 case FM_ON:
1119 if(af_enabled && (freq != prev_freq)
1120 && (prev_freq > 0)) {
1121 ALOGI("AF jump happened\n");
1122 is_af_jump_received = true;
1123 }
1124 break;
1125 case FM_TUNE_IN_PROGRESS:
1126 pthread_mutex_lock(&mutex_tune_compl_cond);
1127 set_fm_state(FM_ON);
1128 pthread_cond_broadcast(&tune_compl_cond);
1129 pthread_mutex_unlock(&mutex_tune_compl_cond);
1130 break;
1131 case SEEK_IN_PROGRESS:
1132 pthread_mutex_lock(&mutex_seek_compl_cond);
1133 set_fm_state(FM_ON);
1134 pthread_cond_broadcast(&seek_compl_cond);
1135 pthread_mutex_unlock(&mutex_seek_compl_cond);
1136 break;
1137 case SCAN_IN_PROGRESS:
1138 break;
1139 }
1140 prev_freq = freq;
1141}
1142
1143void FmRadioController :: handle_seek_next_event
1144(
1145 void
1146)
1147{
1148 ALOGI("FM handle seek next event\n");
1149}
1150
1151void FmRadioController :: handle_seek_complete_event
1152(
1153 void
1154)
1155{
1156 ALOGI("FM handle seek complete event\n");
1157}
1158
1159void FmRadioController :: handle_raw_rds_event
1160(
1161 void
1162)
1163{
1164
1165}
1166
1167void FmRadioController :: handle_rt_event
1168(
1169 void
1170)
1171{
1172 ALOGI("FM handle RT event\n");
1173 is_rt_event_received = true;
1174}
1175
1176void FmRadioController :: handle_ps_event
1177(
1178 void
1179)
1180{
1181 ALOGI("FM handle PS event\n");
1182 is_ps_event_received = true;
1183}
1184
1185void FmRadioController :: handle_error_event
1186(
1187 void
1188)
1189{
1190
1191}
1192
1193void FmRadioController :: handle_below_th_event
1194(
1195 void
1196)
1197{
1198
1199}
1200
1201void FmRadioController :: handle_above_th_event
1202(
1203 void
1204)
1205{
1206
1207}
1208
1209void FmRadioController :: handle_stereo_event
1210(
1211 void
1212)
1213{
1214
1215}
1216void FmRadioController :: handle_mono_event
1217(
1218 void
1219)
1220{
1221
1222}
1223
1224void FmRadioController :: handle_rds_aval_event
1225(
1226 void
1227)
1228{
1229 ALOGI("Got rds_aval_event\n");
1230 is_rds_support = true;
1231}
1232
1233void FmRadioController :: handle_rds_not_aval_event
1234(
1235 void
1236)
1237{
1238 ALOGI("Got rds_not_aval_event\n");
1239}
1240
1241void FmRadioController :: handle_srch_list_event
1242(
1243 void
1244)
1245{
1246 ALOGI("Got srch list event\n");
1247 if (cur_fm_state == SCAN_IN_PROGRESS) {
1248 pthread_mutex_lock(&mutex_scan_compl_cond);
1249 set_fm_state(FM_ON);
1250 pthread_cond_broadcast(&scan_compl_cond);
1251 pthread_mutex_unlock(&mutex_scan_compl_cond);
1252 }
1253}
1254
1255void FmRadioController :: handle_af_list_event
1256(
1257 void
1258)
1259{
1260 char raw_rds[STD_BUF_SIZE];
1261 int ret;
1262 int aflist_size;
1263 ULINT lower_band;
1264 int AfList[MAX_AF_LIST_SIZE];
1265
1266 ALOGI("Got af list event\n");
1267 ret = FmIoctlsInterface::get_buffer(fd_driver,
1268 raw_rds, STD_BUF_SIZE, AF_LIST_IND);
1269 lower_band = FmIoctlsInterface::get_lowerband_limit(fd_driver,
1270 lower_band);
1271 ALOGI("raw_rds[0]: %d\n", (raw_rds[0] & 0xff));
1272 ALOGI("raw_rds[1]: %d\n", (raw_rds[1] & 0xff));
1273 ALOGI("raw_rds[2]: %d\n", (raw_rds[2] & 0xff));
1274 ALOGI("raw_rds[3]: %d\n", (raw_rds[3] & 0xff));
1275 ALOGI("raw_rds[4]: %d\n", (raw_rds[4] & 0xff));
1276 ALOGI("raw_rds[5]: %d\n", (raw_rds[5] & 0xff));
1277 ALOGI("raw_rds[6]: %d\n", (raw_rds[6] & 0xff));
1278
1279 aflist_size = raw_rds[AF_SIZE_IDX] & 0xff;
1280 for(int i = 0; i < aflist_size; i++) {
1281 AfList[i] = (raw_rds[AF_SIZE_IDX + i * NO_OF_BYTES_AF + 1] & 0xFF) |
1282 ((raw_rds[AF_SIZE_IDX + i * NO_OF_BYTES_AF + 2] & 0xFF) << 8) |
1283 ((raw_rds[AF_SIZE_IDX + i * NO_OF_BYTES_AF + 3] & 0xFF) << 16) |
1284 ((raw_rds[AF_SIZE_IDX + i * NO_OF_BYTES_AF + 4] & 0xFF) << 24);
1285 ALOGI("AF: %d\n", AfList[i]);
1286 }
1287}
1288
1289void FmRadioController :: handle_disabled_event
1290(
1291 void
1292)
1293{
1294 //Expected disabled
1295 if(cur_fm_state == FM_OFF_IN_PROGRESS) {
1296 ALOGI("Expected disabled event\n");
1297 }else {//Enexpected disabled
1298 ALOGI("Unexpected disabled event\n");
1299 }
1300
1301 set_fm_state(FM_OFF);
1302 close(fd_driver);
1303 fd_driver = -1;
1304
1305 //allow tune function to exit
1306 pthread_mutex_lock(&mutex_tune_compl_cond);
1307 pthread_cond_broadcast(&tune_compl_cond);
1308 pthread_mutex_unlock(&mutex_tune_compl_cond);
1309 //allow scan function to exit
1310 pthread_mutex_lock(&mutex_scan_compl_cond);
1311 pthread_cond_broadcast(&scan_compl_cond);
1312 pthread_mutex_unlock(&mutex_scan_compl_cond);
1313 //Allow seek function to exit
1314 pthread_mutex_lock(&mutex_seek_compl_cond);
1315 pthread_cond_broadcast(&seek_compl_cond);
1316 pthread_mutex_unlock(&mutex_seek_compl_cond);
1317}
1318
1319void FmRadioController :: handle_rds_grp_mask_req_event
1320(
1321 void
1322)
1323{
1324 SetRdsGrpMask(0);
1325}
1326
1327void FmRadioController :: handle_rt_plus_event
1328(
1329 void
1330)
1331{
1332 ALOGI("FM handle RT Plus event\n");
1333}
1334
1335void FmRadioController :: handle_af_jmp_event
1336(
1337 void
1338)
1339{
1340 long freq = -1;
1341
1342 freq = GetChannel();
1343 ALOGI("FM handle AF Jumped event\n");
1344 if(af_enabled && (freq != prev_freq)) {
1345 ALOGI("AF Jump occured, prevfreq is: %ld, af freq is: %ld\n", prev_freq, freq);
1346 }
1347 prev_freq = freq;
1348}
1349
1350void FmRadioController :: handle_ert_event
1351(
1352 void
1353)
1354{
1355 ALOGI("FM handle ERT event\n");
1356}
1357
1358bool FmRadioController :: process_radio_events
1359(
1360 int event
1361)
1362{
1363 bool ret = true;
1364
1365 switch(event) {
1366 case READY_EVENT:
1367 handle_enabled_event();
1368 break;
1369 case TUNE_EVENT:
1370 handle_tuned_event();
1371 break;
1372 case SEEK_COMPLETE_EVENT:
1373 handle_seek_complete_event();
1374 break;
1375 case SCAN_NEXT_EVENT:
1376 handle_seek_next_event();
1377 break;
1378 case RAW_RDS_EVENT:
1379 handle_raw_rds_event();
1380 break;
1381 case RT_EVENT:
1382 handle_rt_event();
1383 break;
1384 case PS_EVENT:
1385 handle_ps_event();
1386 break;
1387 case ERROR_EVENT:
1388 handle_error_event();
1389 break;
1390 case BELOW_TH_EVENT:
1391 handle_below_th_event();
1392 break;
1393 case ABOVE_TH_EVENT:
1394 handle_above_th_event();
1395 break;
1396 case STEREO_EVENT:
1397 handle_stereo_event();
1398 break;
1399 case MONO_EVENT:
1400 handle_mono_event();
1401 break;
1402 case RDS_AVAL_EVENT:
1403 handle_rds_aval_event();
1404 break;
1405 case RDS_NOT_AVAL_EVENT:
1406 handle_rds_not_aval_event();
1407 break;
1408 case SRCH_LIST_EVENT:
1409 handle_srch_list_event();
1410 break;
1411 case AF_LIST_EVENT:
1412 handle_af_list_event();
1413 break;
1414 case DISABLED_EVENT:
1415 handle_disabled_event();
1416 ret = false;
1417 break;
1418 case RDS_GRP_MASK_REQ_EVENT:
1419 handle_rds_grp_mask_req_event();
1420 break;
1421 case RT_PLUS_EVENT:
1422 handle_rt_plus_event();
1423 break;
1424 case ERT_EVENT:
1425 handle_ert_event();
1426 break;
1427 case AF_JMP_EVENT:
1428 handle_af_jmp_event();
1429 break;
1430 default:
1431 break;
1432 }
1433 return ret;
1434}