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