1 /* 2 * TI FM kernel driver's sample application. 3 * 4 * Copyright (C) 2010 Texas Instruments 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * 19 */ 20 21 #include <stdio.h> 22 #include <fcntl.h> 23 #include <linux/videodev2.h> 24 #include <math.h> 25 #include <pthread.h> 26 #include <errno.h> 27 #include <signal.h> 28 #include <string.h> 29 #include <stdlib.h> 30 #include <tinyalsa/asoundlib.h> 31 #include <poll.h> 32 33 #include "kfmapp.h" 34 35 static unsigned int pdevice = 0; /* playback device */ 36 static unsigned int cdevice = 1; /* capture device */ 37 static int fm_aud_enable; 38 struct pcm *pcm_p = NULL; 39 struct pcm *pcm_c = NULL; 40 struct mixer *mixer; 41 42 /* #define V4L2_TUNER_SUB_RDS 0x10 */ 43 44 static char *g_mutemodes[]={"Mute ON","Mute OFF","Attenuate Voice"}; 45 /* 46 static char *g_bands[]={"Europe/US","Japan"}; 47 static char *g_sm_modes[]={"Stereo","Mono"}; 48 static char *g_rx_deemphasis_modes[]={"50 usec","75 usec"}; 49 static char *g_rds_opmodes[]={"RDS","RBDS"}; 50 static char *g_af_switch_mode[]={"Off","On"}; 51 */ 52 static char *g_rds_modes[]={"Off","On"}; 53 static int g_vol_to_set; 54 static pthread_t g_rds_thread_ptr; 55 volatile char g_rds_thread_terminate,g_rds_thread_running; 56 57 static int g_radio_fd; 58 59 /* Program Type */ 60 static char *pty_str[]= {"None", "News", "Current Affairs", 61 "Information","Sport", "Education", 62 "Drama", "Culture","Science", 63 "Varied Speech", "Pop Music", 64 "Rock Music","Easy Listening", 65 "Light Classic Music", "Serious Classics", 66 "other Music","Weather", "Finance", 67 "Childrens Progs","Social Affairs", 68 "Religion", "Phone In", "Travel", 69 "Leisure & Hobby","Jazz", "Country", 70 "National Music","Oldies","Folk", 71 "Documentary", "Alarm Test", "Alarm"}; 72 73 void fmapp_display_tx_menu(void) 74 { 75 printf("Available FM TX Commands:\n"); 76 printf("f <freq> tune to freq(in MHz)\n"); 77 printf("gf get frequency(MHz)\n"); 78 printf("e <val> set pre-emphasis filter value" 79 "(0 = OFF, 1 = 50 usec and 2 = 75 usec)\n"); 80 /* printf("ge get pre-emphasis filter\n");*/ 81 printf("p <val> set FM TX powerlevel (91 - 122)\n"); 82 /* printf("gp get deemphasis filter\n"); 83 printf("i <val> set FM TX antenna impedance value (0 = 50, 1 = 200 and 2 = 500)\n"); 84 printf("gi get FM TX antenna impedance value\n");*/ 85 printf("1 to set RDS Radio Text\n"); 86 printf("2 to set RDS Radio PS Name\n"); 87 printf("3 <value> to set RDS Radio PI code\n"); 88 printf("4 <value> to set RDS Radio PTY\n"); 89 printf("5 <AF Freq in KHz> to set RDS Radio Alternate Frequency\n"); 90 } 91 void fmapp_display_rx_menu(void) 92 { 93 printf("Available FM RX Commands:\n"); 94 /* printf("p power on/off\n"); */ 95 printf("f <freq> tune to freq(in MHz)\n"); 96 printf("gf get frequency(MHz)\n"); 97 printf("gr get rssi level\n"); 98 printf("t turns RDS on/off\n"); 99 printf("gt get RDS on/off\n"); 100 printf("+ increases the volume\n"); 101 printf("- decreases the volume\n"); 102 printf("v <0-65535> sets the volume\n"); 103 printf("gv get volume\n"); 104 printf("b<value> switches Japan / Eur-Us (0=US/Eur & 1=Japan)\n"); 105 printf("gb get band\n"); 106 printf("s switches stereo / mono\n"); 107 printf("gs get stereo/mono mode\n"); 108 printf("m changes mute mode\n"); 109 printf("gm get mute mode\n"); 110 /* printf("e set deemphasis filter\n"); 111 printf("ge get deemphasis filter\n"); 112 printf("d set rf dependent mute\n"); 113 printf("gd get rf dependent mute\n"); 114 printf("z set rds system\n"); 115 printf("gz get rds system\n"); */ 116 printf("c<value> set rds af switch(0-OFF & 1=ON)\n"); 117 printf("gc get rds af switch\n"); 118 printf("< seek down\n"); 119 printf("> seek up\n"); 120 printf("? <(0)-(127)> set RSSI threshold\n"); 121 printf("g? get rssi threshold\n"); 122 printf("ga get tuner attributes\n"); 123 /* printf("gn auto scan\n"); */ 124 printf("A Start FM RX Audio Routing\n"); 125 printf("q quit rx menu\n"); 126 } 127 int fmapp_get_tx_ant_imp(void) 128 { 129 struct v4l2_control vctrl; 130 int res; 131 132 vctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR; 133 134 res = ioctl(g_radio_fd,VIDIOC_G_CTRL,&vctrl); 135 if(res < 0) 136 { 137 printf("Failed to get FM Tx antenna impedence value\n"); 138 return res; 139 } 140 141 printf("FM Tx antenna impedence value is --> %d\n",vctrl.value); 142 return 0; 143 } 144 145 int fmapp_get_tx_power_level(void) 146 { 147 struct v4l2_control vctrl; 148 int res; 149 150 vctrl.id = V4L2_CID_TUNE_POWER_LEVEL; 151 152 res = ioctl(g_radio_fd,VIDIOC_G_CTRL,&vctrl); 153 if(res < 0) 154 { 155 printf("Failed to get FM Tx power level\n"); 156 return res; 157 } 158 159 printf("FM Tx Power level is --> %d\n",vctrl.value); 160 return 0; 161 } 162 int fmapp_get_premphasis_filter_mode(void) 163 { 164 struct v4l2_control vctrl; 165 int res; 166 167 vctrl.id = V4L2_CID_TUNE_PREEMPHASIS; 168 169 res = ioctl(g_radio_fd,VIDIOC_G_CTRL,&vctrl); 170 if(res < 0) 171 { 172 printf("Failed to get preemphasis filter val\n"); 173 return res; 174 } 175 176 printf("Preemphasis filter val is --> %d\n",vctrl.value); 177 return 0; 178 } 179 int fmapp_get_tx_frequency(void) 180 { 181 struct v4l2_frequency vf; 182 struct v4l2_modulator vm; 183 int res, div; 184 185 vm.index = 0; 186 res = ioctl(g_radio_fd, VIDIOC_G_MODULATOR, &vm); 187 if(res < 0) 188 { 189 printf("Failed to get modulator capabilities\n"); 190 return res; 191 } 192 193 res = ioctl(g_radio_fd, VIDIOC_G_FREQUENCY,&vf); 194 if(res < 0) 195 { 196 printf("Failed to read current frequency\n"); 197 return res; 198 } 199 200 div = (vm.capability & V4L2_TUNER_CAP_LOW) ? 1000 : 1; 201 202 printf("Transmitting at Frequency %3.2f MHz\n",vf.frequency / 203 ( 16000.0 * div)); 204 return 0; 205 } 206 int fmapp_get_rx_frequency(void) 207 { 208 struct v4l2_frequency vf; 209 struct v4l2_tuner vt; 210 int res, div; 211 212 vt.index = 0; 213 res = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vt); 214 if(res < 0) 215 { 216 printf("Failed to get tuner capabilities\n"); 217 return res; 218 } 219 220 res = ioctl(g_radio_fd, VIDIOC_G_FREQUENCY,&vf); 221 if(res < 0) 222 { 223 printf("Failed to read current frequency\n"); 224 return res; 225 } 226 227 div = (vt.capability & V4L2_TUNER_CAP_LOW) ? 1000 : 1; 228 229 printf("Tuned to frequency %3.2f MHz \n",vf.frequency / ( 16.0 * div)); 230 return 0; 231 } 232 233 int fmapp_set_tx_rds_radio_text(void) 234 { 235 struct v4l2_ext_controls_kfmapp vec; 236 struct v4l2_ext_control_kfmapp vctrls; 237 int res; 238 char rds_text[100]; 239 240 vec.ctrl_class = V4L2_CTRL_CLASS_FM_TX; 241 vec.count = 1; 242 vctrls.id = V4L2_CID_RDS_TX_RADIO_TEXT; 243 printf("Enter RDS text to transmit\n"); 244 scanf("%s", rds_text); 245 vctrls.string = rds_text; 246 vctrls.size = strlen(rds_text) + 1; 247 vec.controls = &vctrls; 248 249 printf("Entered RDS text is - %s and strlen = %d\n",vctrls.string, vctrls.size); 250 res = ioctl(g_radio_fd, VIDIOC_S_EXT_CTRLS, &vec); 251 if(res < 0) 252 { 253 printf("Failed to set FM Tx RDS Radio text\n"); 254 return res; 255 } 256 257 printf("FM Modulator RDS Radio text is set and transmitted\n"); 258 259 return res; 260 } 261 262 int fmapp_set_tx_rds_radio_ps_name(void) 263 { 264 struct v4l2_ext_controls_kfmapp vec; 265 struct v4l2_ext_control_kfmapp vctrls; 266 int res; 267 char rds_text[100]; 268 269 vec.ctrl_class = V4L2_CTRL_CLASS_FM_TX; 270 vec.count = 1; 271 vctrls.id = V4L2_CID_RDS_TX_PS_NAME; 272 printf("Enter RDS PS Name to transmit\n"); 273 scanf("%s", rds_text); 274 vctrls.string = rds_text; 275 vctrls.size = strlen(rds_text) + 1; 276 vec.controls = &vctrls; 277 278 printf("Entered RDS text is - %s\n",vctrls.string); 279 res = ioctl(g_radio_fd, VIDIOC_S_EXT_CTRLS, &vec); 280 if(res < 0) 281 { 282 printf("Failed to set FM Tx RDS Radio PS Name\n"); 283 return res; 284 } 285 286 printf("FM Modulator RDS Radio PS Name set and transmitted\n"); 287 288 return res; 289 } 290 291 int fmapp_set_tx_rds_radio_pi_code(char *cmd) 292 { 293 struct v4l2_ext_controls_kfmapp vec; 294 struct v4l2_ext_control_kfmapp vctrls; 295 int user_val; 296 int res; 297 298 sscanf(cmd, "%d", &user_val); 299 300 vec.ctrl_class = V4L2_CTRL_CLASS_FM_TX; 301 vec.count = 1; 302 vctrls.id = V4L2_CID_RDS_TX_PI; 303 vctrls.value = user_val; 304 vctrls.size = 0; 305 vec.controls = &vctrls; 306 307 res = ioctl(g_radio_fd, VIDIOC_S_EXT_CTRLS, &vec); 308 if(res < 0) 309 { 310 printf("Failed to set FM Tx RDS PI Code\n"); 311 return res; 312 } 313 314 printf("Setting FM Tx RDS PI Code is Succesful\n"); 315 316 return res; 317 318 } 319 320 int fmapp_set_tx_rds_radio_af(char *cmd) 321 { 322 int fd, res, af_freq; 323 324 fd = open(FMTX_RDS_AF_SYSFS_ENTRY, O_RDWR); 325 if (fd < 0) { 326 printf("Can't open %s", FMTX_RDS_AF_SYSFS_ENTRY); 327 return -1; 328 } 329 330 res = write(fd, cmd, FMAPP_AF_MAX_FREQ_RANGE); 331 if(res <= 0){ 332 printf("Failed to set FM TX RDS Alternate Frequency\n"); 333 goto exit; 334 } 335 336 printf("FM RDS Alternate Frequency is to %s Succesfully\n", cmd); 337 exit: 338 close(fd); 339 return res; 340 341 } 342 int fmapp_set_tx_rds_radio_pty(char *cmd) 343 { 344 struct v4l2_ext_controls_kfmapp vec; 345 struct v4l2_ext_control_kfmapp vctrls; 346 int user_val; 347 int res; 348 349 sscanf(cmd, "%d", &user_val); 350 351 vec.ctrl_class = V4L2_CTRL_CLASS_FM_TX; 352 vec.count = 1; 353 vctrls.id = V4L2_CID_RDS_TX_PTY; 354 vctrls.value = user_val; 355 vctrls.size = 0; 356 vec.controls = &vctrls; 357 358 res = ioctl(g_radio_fd, VIDIOC_S_EXT_CTRLS, &vec); 359 if(res < 0) 360 { 361 printf("Failed to set FM Tx RDS PTY\n"); 362 return res; 363 } 364 365 printf("Setting FM Tx RDS PTY is Succesful\n"); 366 367 return res; 368 369 } 370 int fmapp_set_tx_ant_imp(char *cmd) 371 { 372 int user_val; 373 struct v4l2_control vctrl; 374 int res; 375 376 sscanf(cmd, "%d", &user_val); 377 378 vctrl.id = V4L2_CID_TUNE_ANTENNA_CAPACITOR; 379 vctrl.value = user_val; 380 res = ioctl(g_radio_fd,VIDIOC_S_CTRL,&vctrl); 381 if(res < 0) 382 { 383 printf("Failed to set FM Tx antenna impedence value\n"); 384 return res; 385 } 386 387 printf("Setting FM Tx antenna impedence value to ---> %d\n",vctrl.value); 388 return 0; 389 } 390 391 int fmapp_set_tx_power_level(char *cmd) 392 { 393 struct v4l2_ext_controls_kfmapp vec; 394 struct v4l2_ext_control_kfmapp vctrls; 395 int user_val; 396 int res; 397 398 sscanf(cmd, "%d", &user_val); 399 400 vec.ctrl_class = V4L2_CTRL_CLASS_FM_TX; 401 vec.count = 1; 402 vctrls.id = V4L2_CID_TUNE_POWER_LEVEL; 403 vctrls.value = user_val; 404 vctrls.size = 0; 405 vec.controls = &vctrls; 406 407 res = ioctl(g_radio_fd, VIDIOC_S_EXT_CTRLS, &vec); 408 if(res < 0) 409 { 410 printf("Failed to set FM Tx power level\n"); 411 return res; 412 } 413 414 printf("Setting FM Tx Power level to ---> %d\n", vctrls.value); 415 416 return res; 417 418 } 419 int fmapp_set_premphasis_filter_mode(char *cmd) 420 { 421 struct v4l2_ext_controls_kfmapp vec; 422 struct v4l2_ext_control_kfmapp vctrls; 423 int user_val; 424 int res; 425 426 sscanf(cmd, "%d", &user_val); 427 428 vec.ctrl_class = V4L2_CTRL_CLASS_FM_TX; 429 vec.count = 1; 430 vctrls.id = V4L2_CID_TUNE_PREEMPHASIS; 431 vctrls.value = user_val; 432 vctrls.size = 0; 433 vec.controls = &vctrls; 434 435 res = ioctl(g_radio_fd, VIDIOC_S_EXT_CTRLS, &vec); 436 if(res < 0) 437 { 438 printf("Failed to set preemphasis filter val\n"); 439 return res; 440 } 441 442 printf("Setting preemphasis filter val success\n"); 443 444 return res; 445 446 } 447 448 int fmapp_set_tx_frequency(char *cmd) 449 { 450 float user_freq; 451 struct v4l2_frequency vf; 452 struct v4l2_modulator vm; 453 int res, div; 454 455 sscanf(cmd, "%f", &user_freq); 456 457 vm.index = 0; 458 res = ioctl(g_radio_fd, VIDIOC_G_MODULATOR, &vm); 459 if(res < 0) 460 { 461 printf("Failed to get modulator capabilities\n"); 462 return res; 463 } 464 465 vf.tuner = 0; 466 vf.frequency = rint(user_freq * 16000 + 0.5); 467 468 div = (vm.capability & V4L2_TUNER_CAP_LOW) ? 1000 : 1; 469 if (div == 1) 470 vf.frequency /= 1000; 471 472 res = ioctl(g_radio_fd, VIDIOC_S_FREQUENCY, &vf); 473 if(res < 0) 474 { 475 printf("Failed to set frequency %f\n",user_freq); 476 return res; 477 } 478 printf("Started Transmitting at %3.2f MHz Frequency\n", vf.frequency / 479 (16.0 * div)); 480 481 return res; 482 } 483 int fmapp_set_rx_frequency(char *cmd) 484 { 485 float user_freq; 486 struct v4l2_frequency vf; 487 struct v4l2_tuner vt; 488 int res, div; 489 490 sscanf(cmd, "%f", &user_freq); 491 492 vf.tuner = 0; 493 /* As per V4L2 specifications VIDIOC_S_FREQUENCY ioctl expects tuning 494 * frequency in units of 62.5 KHz, or if the struct v4l2_tuner or struct 495 * v4l2_modulator capabilities flag V4L2_TUNER_CAP_LOW is set, in units 496 * of 62.5 Hz. But FM ST v4l2 driver presently handling the frequency in 497 * units of 1 KHz 498 */ 499 vf.frequency = rint(user_freq * 16000 + 0.5); 500 501 vt.index = 0; 502 res = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vt); 503 if(res < 0) 504 { 505 printf("Failed to get tuner capabilities\n"); 506 return res; 507 } 508 509 div = (vt.capability & V4L2_TUNER_CAP_LOW) ? 1000 : 1; 510 if (div == 1) 511 vf.frequency /= 1000; 512 513 if(vf.frequency < vt.rangelow || vf.frequency > vt.rangehigh){ 514 printf("Failed to set frequency: Frequency is not in range" 515 "(%3.2f MHz to %3.2f MHz)\n", (vt.rangelow/(16.0 * div)), 516 (vt.rangehigh/(16.0 * div))); 517 return -EINVAL; 518 } 519 520 res = ioctl(g_radio_fd, VIDIOC_S_FREQUENCY, &vf); 521 if(res < 0) 522 { 523 printf("Failed to set frequency %f\n",user_freq); 524 return res; 525 } 526 printf("Tuned to frequency %3.2f MHz\n", vf.frequency / (16.0 * div)); 527 return 0; 528 } 529 530 inline void display_volume_bar(void) 531 { 532 int index; 533 printf("\nVolume: "); 534 for(index=1; index<g_vol_to_set; index = index*1000) 535 printf("#"); 536 537 printf("\nVolume is : %d\n",g_vol_to_set); 538 539 } 540 int fmapp_set_rx_volume(char *cmd,int interactive,int vol_to_set) 541 { 542 struct v4l2_control vctrl; 543 int res; 544 545 if(interactive == FMAPP_INTERACTIVE) 546 sscanf(cmd, "%d", &g_vol_to_set); 547 else 548 g_vol_to_set = vol_to_set; 549 550 vctrl.id = V4L2_CID_AUDIO_VOLUME; 551 vctrl.value = g_vol_to_set; 552 res = ioctl(g_radio_fd,VIDIOC_S_CTRL,&vctrl); 553 if(res < 0) 554 { 555 g_vol_to_set = 0; 556 printf("Failed to set volume\n"); 557 return res; 558 } 559 printf("Setting volume to %d \n",g_vol_to_set); 560 return 0; 561 } 562 563 int fmapp_get_rx_volume(void) 564 { 565 struct v4l2_control vctrl; 566 int res; 567 568 vctrl.id = V4L2_CID_AUDIO_VOLUME; 569 res = ioctl(g_radio_fd,VIDIOC_G_CTRL,&vctrl); 570 if(res < 0) 571 { 572 printf("Failed to get volume\n"); 573 return res; 574 } 575 g_vol_to_set = vctrl.value; 576 577 printf("Radio Volume is set to %d\n",g_vol_to_set); 578 // display_volume_bar(); 579 return 0; 580 } 581 582 int fmapp_rx_increase_volume(void) 583 { 584 int ret; 585 586 g_vol_to_set +=1; 587 if(g_vol_to_set > 70) 588 g_vol_to_set = 70; 589 590 ret = fmapp_set_rx_volume(NULL,FMAPP_BATCH,g_vol_to_set); 591 if(ret < 0) 592 return ret; 593 594 display_volume_bar(); 595 return 0; 596 } 597 int fmapp_rx_decrease_volume(void) 598 { 599 int ret; 600 g_vol_to_set -=1; 601 if(g_vol_to_set < 0) 602 g_vol_to_set = 0; 603 604 ret = fmapp_set_rx_volume(NULL,FMAPP_BATCH,g_vol_to_set); 605 if(ret < 0) 606 return ret; 607 608 display_volume_bar(); 609 return 0; 610 } 611 int fmapp_set_rx_mute_mode(void) 612 { 613 struct v4l2_control vctrl; 614 static short int mute_mode = FM_MUTE_OFF; 615 int res; 616 617 vctrl.value = 0; 618 printf("Mutemode = %d\n",mute_mode); 619 switch (mute_mode) 620 { 621 case FM_MUTE_OFF: 622 mute_mode = FM_MUTE_ON; 623 break; 624 625 case FM_MUTE_ON: 626 mute_mode = FM_MUTE_OFF; 627 break; 628 } 629 630 vctrl.id = V4L2_CID_AUDIO_MUTE; 631 vctrl.value = mute_mode; 632 res = ioctl(g_radio_fd,VIDIOC_S_CTRL,&vctrl); 633 if(res < 0) 634 { 635 printf("Failed to set mute mode\n"); 636 return res; 637 } 638 639 printf("Setting to \"%s\" \n",g_mutemodes[mute_mode]); 640 return 0; 641 } 642 int fmapp_get_rx_mute_mode(void) 643 { 644 struct v4l2_control vctrl; 645 int res; 646 647 vctrl.id = V4L2_CID_AUDIO_MUTE; 648 res = ioctl(g_radio_fd,VIDIOC_G_CTRL,&vctrl); 649 if(res < 0) 650 { 651 printf("Failed to get mute mode\n"); 652 return res; 653 } 654 655 printf("%s\n",g_mutemodes[vctrl.value]); 656 return 0; 657 } 658 int fmapp_rx_seek(int seek_direction) 659 { 660 struct ti_v4l2_hw_freq_seek frq_seek; 661 int res; 662 663 printf("Seeking %s..\n",seek_direction?"up":"down"); 664 frq_seek.type = 1; 665 frq_seek.seek_upward = seek_direction; 666 frq_seek.spacing = 200000; 667 frq_seek.wrap_around = 0; 668 errno = 0; 669 res = ioctl(g_radio_fd,VIDIOC_S_HW_FREQ_SEEK,&frq_seek); 670 if(errno == EAGAIN) 671 { 672 printf("Band limit reached\n"); 673 } 674 else if(res <0) 675 { 676 printf("Seek operation failed\n"); 677 return res; 678 } 679 /* Display seeked freq */ 680 fmapp_get_rx_frequency(); 681 return 0; 682 } 683 684 int fmapp_set_rx_af_switch(char *cmd) 685 { 686 int fd, res; 687 688 fd = open(FMRX_RDS_AF_SYSFS_ENTRY, O_RDWR); 689 if (fd < 0) { 690 printf("Can't open %s", FMRX_RDS_AF_SYSFS_ENTRY); 691 return -1; 692 } 693 694 res = write(fd, cmd, sizeof(char)); 695 if(res <= 0){ 696 printf("Failed to set FM RDS AF Switch\n"); 697 goto exit; 698 } 699 700 printf("FM RDS Alternate Frequency is %s\n", 701 atoi(cmd) == 0 ? "OFF":"ON"); 702 exit: 703 close(fd); 704 return res; 705 } 706 707 int fmapp_get_rx_af_switch(void) 708 { 709 unsigned char fm_rds_af; 710 int fd, res; 711 712 fd = open(FMRX_RDS_AF_SYSFS_ENTRY, O_RDONLY); 713 if (fd < 0) { 714 printf("Can't open %s", FMRX_RDS_AF_SYSFS_ENTRY); 715 return -1; 716 } 717 718 res = read(fd, &fm_rds_af, 1); 719 if(res < 0){ 720 printf("reading %s failed %s\n", 721 FMRX_RDS_AF_SYSFS_ENTRY,strerror(res)); 722 goto exit; 723 } 724 725 printf("FM RDS Alternate Frequency is %s \n", 726 (atoi((char *) &fm_rds_af)) == 0?"OFF":"ON"); 727 exit: 728 close(fd); 729 return 0; 730 } 731 732 int fmapp_get_rx_rssi_threshold(void) 733 { 734 unsigned char fm_rssi_threshhold; 735 int fd, res; 736 737 fd = open(FMRX_RSSI_LVL_SYSFS_ENTRY, O_RDONLY); 738 if (fd < 0) { 739 printf("Can't open %s", FMRX_RSSI_LVL_SYSFS_ENTRY); 740 return -1; 741 } 742 743 res = read(fd, &fm_rssi_threshhold, 3); 744 if(res < 0){ 745 printf("reading %s failed %s\n", 746 FMRX_RSSI_LVL_SYSFS_ENTRY,strerror(res)); 747 goto exit; 748 } 749 750 printf("Current FM RSSI threshold level is %d \n", 751 atoi((char *) &fm_rssi_threshhold)); 752 753 exit: 754 close(fd); 755 return res; 756 } 757 758 int fmapp_set_rx_rssi_threshold(char *cmd) 759 { 760 int fd, res; 761 762 fd = open(FMRX_RSSI_LVL_SYSFS_ENTRY, O_RDWR); 763 if (fd < 0) { 764 printf("Can't open %s", FMRX_RSSI_LVL_SYSFS_ENTRY); 765 return -1; 766 } 767 768 res = write(fd, cmd, sizeof(char) * 3); 769 if(res <= 0){ 770 printf("Failed to set FM RSSI threshold level\n"); 771 goto exit; 772 } 773 774 printf("FM RSSI threshold level is set to %d\n", atoi(cmd)); 775 776 exit: 777 close(fd); 778 return res; 779 } 780 781 int fmapp_set_band(char *cmd) 782 { 783 int fd, res; 784 785 fd = open(FMRX_BAND_SYSFS_ENTRY, O_RDWR); 786 if (fd < 0) { 787 printf("Can't open %s", FMRX_BAND_SYSFS_ENTRY); 788 return -1; 789 } 790 791 res = write(fd, cmd, sizeof(char)); 792 if(res <= 0){ 793 printf("Failed to set FM Band\n"); 794 goto exit; 795 } 796 797 printf("FM Band is set to %s\n", atoi(cmd) == 0?"US/EUROPE":"JAPAN"); 798 exit: 799 close(fd); 800 return res; 801 } 802 803 int fmapp_get_band(void) 804 { 805 unsigned char fm_band; 806 int fd, res; 807 808 fd = open(FMRX_BAND_SYSFS_ENTRY, O_RDONLY); 809 if (fd < 0) { 810 printf("Can't open %s", FMRX_BAND_SYSFS_ENTRY); 811 return -1; 812 } 813 814 res = read(fd, &fm_band, 1); 815 if(res < 0){ 816 printf("reading %s failed %s\n",FMRX_BAND_SYSFS_ENTRY,strerror(res)); 817 goto exit; 818 } 819 820 printf("Present FM Band is %s \n", 821 (atoi((char *) &fm_band)) == 0?"US/EUROPE":"JAPAN"); 822 exit: 823 close(fd); 824 return res; 825 } 826 static void tinymix_set_value(struct mixer *mixer, unsigned int id, 827 int value) 828 { 829 struct mixer_ctl *ctl; 830 enum mixer_ctl_type type; 831 unsigned int i, num_values; 832 833 ctl = mixer_get_ctl(mixer, id); 834 type = mixer_ctl_get_type(ctl); 835 num_values = mixer_ctl_get_num_values(ctl); 836 837 for(i=0; i<num_values; i++) { 838 if (mixer_ctl_set_value(ctl, i, value)) { 839 fprintf(stderr, "Error: invalid value\n"); 840 return; 841 } 842 } 843 } 844 845 int fmapp_start_audio() 846 { 847 struct pcm_config config; 848 849 mixer = mixer_open(0); 850 if (!mixer) { 851 fprintf(stderr, "Failed to open mixer\n"); 852 return EXIT_FAILURE; 853 } 854 855 config.channels = 2; 856 config.rate = 48000; 857 config.period_size = 1024; 858 config.period_count = 4; 859 config.format = PCM_FORMAT_S16_LE; 860 config.silence_threshold = 0; 861 config.stop_threshold = -1; 862 863 if (fm_aud_enable == 0){ 864 /* Set Tinymix controles */ 865 tinymix_set_value(mixer, 77, 2); 866 tinymix_set_value(mixer, 76, 2); 867 tinymix_set_value(mixer, 64, 1); 868 tinymix_set_value(mixer, 65, 4); 869 tinymix_set_value(mixer, 55, 12); 870 tinymix_set_value(mixer, 54, 11); 871 tinymix_set_value(mixer, 51, 1); 872 tinymix_set_value(mixer, 9, 120); 873 tinymix_set_value(mixer, 72, 1); 874 tinymix_set_value(mixer, 73, 1); 875 tinymix_set_value(mixer, 34, 1); 876 tinymix_set_value(mixer, 50, 1); 877 878 pcm_p = pcm_open(0, pdevice, PCM_OUT, &config); 879 if (!pcm_p || !pcm_is_ready(pcm_p)) { 880 fprintf(stderr, "Unable to open PCM device (%s)\n", 881 pcm_get_error(pcm_p)); 882 return 0; 883 } 884 printf("Playback device opened successfully"); 885 pcm_c = pcm_open(0, cdevice, PCM_IN, &config); 886 if (!pcm_c || !pcm_is_ready(pcm_c)) { 887 fprintf(stderr, "Unable to open PCM device (%s)\n", 888 pcm_get_error(pcm_c)); 889 return 0; 890 } 891 printf("Capture device opened successfully"); 892 pcm_start(pcm_c); 893 pcm_start(pcm_p); 894 printf(" Trigered the loopback"); 895 fm_aud_enable = 1; 896 } 897 else { 898 /* Set Tinymix controls to Normal*/ 899 tinymix_set_value(mixer, 77, 0); 900 tinymix_set_value(mixer, 76, 0); 901 tinymix_set_value(mixer, 64, 0); 902 tinymix_set_value(mixer, 65, 0); 903 tinymix_set_value(mixer, 55, 0); 904 tinymix_set_value(mixer, 54, 0); 905 tinymix_set_value(mixer, 51, 0); 906 tinymix_set_value(mixer, 9, 0); 907 tinymix_set_value(mixer, 72, 0); 908 tinymix_set_value(mixer, 73, 0); 909 tinymix_set_value(mixer, 34, 0); 910 tinymix_set_value(mixer, 50, 0); 911 912 /* close the device */ 913 pcm_stop(pcm_p); 914 pcm_stop(pcm_c); 915 pcm_close(pcm_p); 916 pcm_close(pcm_c); 917 fm_aud_enable = 0; 918 } 919 printf("FM RX Audio Routing Done\n"); 920 return 0; 921 } 922 923 int fmapp_get_rx_rssi_lvl(void) 924 { 925 struct v4l2_tuner vtun; 926 float rssi_lvl; 927 int res; 928 929 vtun.index = 0; 930 res = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); 931 if(res < 0) 932 { 933 printf("Failed to get tunner attributes\n"); 934 return res; 935 } 936 rssi_lvl = ((float)vtun.signal / 0xFFFF) * 100; 937 printf("Signal Strength: %d%%\n",(unsigned int)rssi_lvl); 938 939 return 0; 940 } 941 int fmapp_set_stereo_mono_mode(void) 942 { 943 struct v4l2_tuner vtun; 944 int res = 0; 945 946 vtun.index = 0; 947 res = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); 948 if(res < 0) 949 { 950 printf("Failed to set stereo-mono mode\n"); 951 return res; 952 } 953 954 if(V4L2_TUNER_MODE_STEREO == vtun.audmode) 955 vtun.audmode = V4L2_TUNER_MODE_MONO; 956 else 957 vtun.audmode = V4L2_TUNER_MODE_STEREO; 958 959 res = ioctl(g_radio_fd, VIDIOC_S_TUNER, &vtun); 960 if(res < 0) 961 { 962 printf("Failed to set stereo-mono mode\n"); 963 return res; 964 } 965 printf("Audio Mode set to: %s\n",(vtun.audmode == V4L2_TUNER_MODE_STEREO) ? "STEREO":"MONO"); 966 967 return 0; 968 } 969 int fmapp_get_stereo_mono_mode(void) 970 { 971 struct v4l2_tuner vtun; 972 int res; 973 974 vtun.index = 0; 975 res = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); 976 if(res < 0) 977 { 978 printf("Failed to get tunner attributes\n"); 979 return res; 980 } 981 printf("Audio Mode: %s\n",(vtun.audmode == V4L2_TUNER_MODE_STEREO) ? "STEREO":"MONO"); 982 983 return 0; 984 } 985 int fmapp_get_rx_tunner_attributes(void) 986 { 987 struct v4l2_tuner vtun; 988 float sigstrength_percentage; 989 int res; 990 991 vtun.index = 0; 992 res = ioctl(g_radio_fd,VIDIOC_G_TUNER,&vtun); 993 if(res < 0) 994 { 995 printf("Failed to get tunner attributes\n"); 996 return res; 997 } 998 printf("-----------------------\n"); 999 printf("Tuner Name: %s\n",vtun.name); 1000 /* TODO: FM driver is not setting V4L2_TUNER_CAP_LOW flag , but its returning vtun.rangelow 1001 * and vtun.rangehigh ranges in HZ . This needs to be corrected in FM driver */ 1002 printf(" Low Freq: %d KHz\n", 1003 (unsigned int )((float)vtun.rangelow * 0.0625)); 1004 printf(" High Freq: %d KHz\n", 1005 (unsigned int) ((float)vtun.rangehigh * 0.0625)); 1006 printf("Audio Mode: %s\n",(vtun.audmode == V4L2_TUNER_MODE_STEREO) ? "STEREO":"MONO"); 1007 sigstrength_percentage = ((float)vtun.signal /0xFFFF) * 100; 1008 printf("Signal Strength: %d%%\n",(unsigned int)sigstrength_percentage); 1009 printf("-----------------------\n"); 1010 return 0; 1011 } 1012 1013 int fmapp_get_scan_valid_frequencies(void) 1014 { 1015 int ret; 1016 struct v4l2_tuner vtun; 1017 struct v4l2_frequency vf; 1018 struct v4l2_control vctrl; 1019 float freq_multiplicator,start_frq,end_frq, 1020 freq,perc,threshold,divide_by; 1021 long totsig; 1022 unsigned char index; 1023 1024 vtun.index = 0; 1025 ret = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); /* get frequency range */ 1026 if (ret < 0) { 1027 printf("Failed to get frequency range"); 1028 return ret; 1029 } 1030 freq_multiplicator = (62.5 * ((vtun.capability & V4L2_TUNER_CAP_LOW) 1031 ? 1 : 1000)); 1032 1033 divide_by = (vtun.capability & V4L2_TUNER_CAP_LOW) ? 1000000 : 1000; 1034 start_frq = ((float)vtun.rangelow * freq_multiplicator)/divide_by; 1035 end_frq = ((float)vtun.rangehigh * freq_multiplicator)/divide_by; 1036 1037 threshold = FMAPP_ASCAN_SIGNAL_THRESHOLD_PER; 1038 1039 /* Enable Mute */ 1040 vctrl.id = V4L2_CID_AUDIO_MUTE; 1041 vctrl.value = FM_MUTE_ON; 1042 ret = ioctl(g_radio_fd,VIDIOC_S_CTRL,&vctrl); 1043 if(ret < 0) 1044 { 1045 printf("Failed to set mute mode\n"); 1046 return ret; 1047 } 1048 printf("Auto Scanning..\n"); 1049 for(freq=start_frq;freq<=end_frq;freq+=0.1) 1050 { 1051 vf.tuner = 0; 1052 vf.frequency = rint(freq*1000); 1053 ret = ioctl(g_radio_fd, VIDIOC_S_FREQUENCY, &vf); /* tune */ 1054 if (ret < 0) { 1055 printf("failed to set freq"); 1056 return ret; 1057 } 1058 totsig = 0; 1059 for(index=0;index<FMAPP_ASCAN_NO_OF_SIGNAL_SAMPLE;index++) 1060 { 1061 vtun.index = 0; 1062 ret = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); /* get info */ 1063 if (ret < 0) { 1064 printf("Failed to get frequency range"); 1065 return ret; 1066 } 1067 totsig += vtun.signal; 1068 perc = (totsig / (65535.0 * index)); 1069 usleep(1); 1070 } 1071 perc = (totsig / (65535.0 * FMAPP_ASCAN_NO_OF_SIGNAL_SAMPLE)); 1072 if ((perc*100.0) > threshold) 1073 printf("%2.1f MHz(%d%%)\n",freq,((unsigned short)(perc * 100.0))); 1074 } 1075 /* Disable Mute */ 1076 vctrl.id = V4L2_CID_AUDIO_MUTE; 1077 vctrl.value = FM_MUTE_OFF; 1078 ret = ioctl(g_radio_fd,VIDIOC_S_CTRL,&vctrl); 1079 if(ret < 0) 1080 { 1081 printf("Failed to set mute mode\n"); 1082 return ret; 1083 } 1084 printf("Scan Completed\n"); 1085 return 0; 1086 } 1087 int fmapp_get_rds_onoff(void) 1088 { 1089 struct v4l2_tuner vtun; 1090 int res = 0; 1091 1092 vtun.index = 0; 1093 res = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); 1094 if(res < 0) 1095 { 1096 printf("Failed to read RDS state\n"); 1097 return res; 1098 } 1099 printf("RDS is: %s\n",(vtun.rxsubchans & V4L2_TUNER_SUB_RDS) ? "ON":"OFF"); 1100 1101 return 0; 1102 } 1103 void fmapp_rds_decode(int blkno, int byte1, int byte2) 1104 { 1105 static char rds_psn[9]; 1106 static char rds_txt[65]; 1107 static int rds_pty,ms_code; 1108 static int group,spare,blkc_byte1,blkc_byte2; 1109 1110 switch (blkno) { 1111 case 0: /* Block A */ 1112 printf("----------------------------------------\n"); 1113 printf("block A - id=%d\n",(byte1 << 8) | byte2); 1114 break; 1115 case 1: /* Block B */ 1116 printf("block B - group=%d%c tp=%d pty=%d spare=%d\n", 1117 (byte1 >> 4) & 0x0f, 1118 ((byte1 >> 3) & 0x01) + 'A', 1119 (byte1 >> 2) & 0x01, 1120 ((byte1 << 3) & 0x18) | ((byte2 >> 5) & 0x07), 1121 byte2 & 0x1f); 1122 group = (byte1 >> 3) & 0x1f; 1123 spare = byte2 & 0x1f; 1124 rds_pty = ((byte1 << 3) & 0x18) | ((byte2 >> 5) & 0x07); 1125 ms_code = (byte2 >> 3)& 0x1; 1126 break; 1127 case 2: /* Block C */ 1128 printf("block C - 0x%02x 0x%02x\n",byte1,byte2); 1129 blkc_byte1 = byte1; 1130 blkc_byte2 = byte2; 1131 break; 1132 case 3 : /* Block D */ 1133 printf("block D - 0x%02x 0x%02x\n",byte1,byte2); 1134 switch (group) { 1135 case 0: /* Group 0A */ 1136 rds_psn[2*(spare & 0x03)+0] = byte1; 1137 rds_psn[2*(spare & 0x03)+1] = byte2; 1138 if ((spare & 0x03) == 0x03) 1139 printf("PSN: %s, PTY: %s, MS: %s\n",rds_psn, 1140 pty_str[rds_pty],ms_code?"Music":"Speech"); 1141 break; 1142 case 4: /* Group 2A */ 1143 rds_txt[4*(spare & 0x0f)+0] = blkc_byte1; 1144 rds_txt[4*(spare & 0x0f)+1] = blkc_byte2; 1145 rds_txt[4*(spare & 0x0f)+2] = byte1; 1146 rds_txt[4*(spare & 0x0f)+3] = byte2; 1147 /* Display radio text once we get 16 characters */ 1148 // if ((spare & 0x0f) == 0x0f) 1149 if (spare > 16) 1150 { 1151 printf("Radio Text: %s\n",rds_txt); 1152 // memset(&rds_txt,0,sizeof(rds_txt)); 1153 } 1154 break; 1155 } 1156 printf("----------------------------------------\n"); 1157 break; 1158 default: 1159 printf("unknown block [%d]\n",blkno); 1160 } 1161 } 1162 void *rds_thread(void *data) 1163 { 1164 unsigned char buf[600]; 1165 int radio_fd; 1166 int ret,index; 1167 struct pollfd pfd; 1168 1169 radio_fd = (int)data; 1170 1171 while(!g_rds_thread_terminate) 1172 { 1173 while(1){ 1174 memset(&pfd, 0, sizeof(pfd)); 1175 pfd.fd = radio_fd; 1176 pfd.events = POLLIN; 1177 ret = poll(&pfd, 1, 10); 1178 if (ret == 0){ 1179 /* Break the poll after RDS data available */ 1180 break; 1181 } 1182 } 1183 1184 ret = read(radio_fd,buf,500); 1185 if(ret < 0) { 1186 1187 break; 1188 } 1189 else if( ret > 0) 1190 { 1191 for(index=0;index<ret;index+=3) 1192 fmapp_rds_decode(buf[index+2] & 0x7,buf[index+1],buf[index]); 1193 } 1194 } 1195 /* TODO: Need to conform thread termination. 1196 * below msg is not coming ,have a doubt on thread termination. 1197 * Fix this later. */ 1198 printf("RDS thread exiting..\n"); 1199 return NULL; 1200 } 1201 int fmapp_set_rds_onoff(unsigned char fmapp_mode) 1202 { 1203 struct v4l2_tuner vtun; 1204 int ret; 1205 static unsigned char rds_mode = FM_RDS_DISABLE; 1206 1207 vtun.index = 0; 1208 ret = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); 1209 if(ret < 0) 1210 { 1211 printf("Failed to get tuner capabilities\n"); 1212 return ret; 1213 } 1214 if(rds_mode == FM_RDS_DISABLE) { 1215 vtun.rxsubchans |= V4L2_TUNER_SUB_RDS; 1216 rds_mode = FM_RDS_ENABLE; 1217 } else { 1218 vtun.rxsubchans &= ~V4L2_TUNER_SUB_RDS; 1219 rds_mode = FM_RDS_DISABLE; 1220 } 1221 1222 ret = ioctl(g_radio_fd, VIDIOC_S_TUNER, &vtun); 1223 if(ret < 0) 1224 { 1225 printf("Failed to set rds on/off status\n"); 1226 return ret; 1227 } 1228 /* Create rds receive thread once */ 1229 if(fmapp_mode == FM_MODE_RX && rds_mode == FM_RDS_ENABLE && 1230 g_rds_thread_running == 0) 1231 { 1232 g_rds_thread_running = 1; 1233 pthread_create(&g_rds_thread_ptr,NULL,rds_thread,(void *)g_radio_fd); 1234 } 1235 1236 printf("RDS %s\n",g_rds_modes[rds_mode]); 1237 return 0; 1238 } 1239 1240 void fmapp_execute_tx_get_command(char *cmd) 1241 { 1242 switch(cmd[0]) 1243 { 1244 case 'f': 1245 fmapp_get_tx_frequency(); 1246 break; 1247 case 'e': 1248 fmapp_get_premphasis_filter_mode(); 1249 break; 1250 case 'p': 1251 fmapp_get_tx_power_level(); 1252 break; 1253 case 'i': 1254 fmapp_get_tx_ant_imp(); 1255 break; 1256 default: 1257 printf("unknown command; type 'h' for help\n"); 1258 } 1259 1260 } 1261 void fmapp_execute_rx_get_command(char *cmd) 1262 { 1263 switch(cmd[0]) 1264 { 1265 case 'f': 1266 fmapp_get_rx_frequency(); 1267 break; 1268 case 'r': 1269 fmapp_get_rx_rssi_lvl(); 1270 break; 1271 case 't': 1272 fmapp_get_rds_onoff(); 1273 break; 1274 case 'v': 1275 fmapp_get_rx_volume(); 1276 break; 1277 case 'm': 1278 fmapp_get_rx_mute_mode(); 1279 break; 1280 case 'b': 1281 fmapp_get_band(); 1282 break; 1283 case 'c': 1284 fmapp_get_rx_af_switch(); 1285 break; 1286 case '?': 1287 fmapp_get_rx_rssi_threshold(); 1288 break; 1289 #if 0 1290 case 'd': 1291 fmapp_get_rfmute(fm_snd_ctrl); 1292 break; 1293 case 'z': 1294 fmapp_get_rds_operation_mode(fm_snd_ctrl); 1295 break; 1296 #endif 1297 case 's': 1298 fmapp_get_stereo_mono_mode(); 1299 break; 1300 #if 0 1301 case 'e': 1302 fmapp_get_rx_deemphasis_filter_mode(fm_snd_ctrl); 1303 break; 1304 #endif 1305 case 'a': 1306 fmapp_get_rx_tunner_attributes(); 1307 break; 1308 #if 0 1309 case 'n': 1310 fmapp_get_scan_valid_frequencies(); 1311 break; 1312 #endif 1313 default: 1314 printf("unknown command; type 'h' for help\n"); 1315 } 1316 } 1317 void fmapp_execute_rx_other_command(char *cmd) 1318 { 1319 switch(cmd[0]) 1320 { 1321 #if 0 1322 case 'p': 1323 fmapp_change_rx_power_mode(fm_snd_ctrl); 1324 break; 1325 #endif 1326 case 'f': 1327 fmapp_set_rx_frequency(cmd+1); 1328 break; 1329 case 't': 1330 fmapp_set_rds_onoff(FM_MODE_RX); 1331 break; 1332 case '+': 1333 fmapp_rx_increase_volume(); 1334 break; 1335 case '-': 1336 fmapp_rx_decrease_volume(); 1337 break; 1338 case 'v': 1339 fmapp_set_rx_volume(cmd+1,FMAPP_INTERACTIVE,0); 1340 break; 1341 case 'm': 1342 fmapp_set_rx_mute_mode(); 1343 break; 1344 case '<': 1345 fmapp_rx_seek(FM_SEARCH_DIRECTION_DOWN); 1346 break; 1347 case '>': 1348 fmapp_rx_seek(FM_SEARCH_DIRECTION_UP); 1349 break; 1350 case 'b': 1351 fmapp_set_band(cmd+1); 1352 break; 1353 case 'h': 1354 fmapp_display_rx_menu(); 1355 break; 1356 case 'c': 1357 fmapp_set_rx_af_switch(cmd+1); 1358 break; 1359 case '?': 1360 fmapp_set_rx_rssi_threshold(cmd+1); 1361 break; 1362 #if 0 1363 case 'd': 1364 fmapp_set_rfmute(fm_snd_ctrl); 1365 break; 1366 case 'z': 1367 fmapp_set_rds_operation_mode(fm_snd_ctrl); 1368 break; 1369 #endif 1370 case 's': 1371 fmapp_set_stereo_mono_mode(); 1372 break; 1373 #if 0 1374 case 'e': 1375 fmapp_set_rx_deemphasis_filter_mode(fm_snd_ctrl); 1376 break; 1377 #endif 1378 case 'A': 1379 fmapp_start_audio(); 1380 break; 1381 } 1382 } 1383 1384 void fmapp_execute_tx_other_command(char *cmd) 1385 { 1386 switch(cmd[0]) 1387 { 1388 case 'f': 1389 fmapp_set_tx_frequency(cmd+1); 1390 break; 1391 case 'e': 1392 fmapp_set_premphasis_filter_mode(cmd+1); 1393 break; 1394 case 'p': 1395 fmapp_set_tx_power_level(cmd+1); 1396 break; 1397 case 'i': 1398 fmapp_set_tx_ant_imp(cmd+1); 1399 break; 1400 case '1': 1401 fmapp_set_tx_rds_radio_text(); 1402 break; 1403 case '2': 1404 fmapp_set_tx_rds_radio_ps_name(); 1405 break; 1406 case '3': 1407 fmapp_set_tx_rds_radio_pi_code(cmd+1); 1408 break; 1409 case '4': 1410 fmapp_set_tx_rds_radio_pty(cmd+1); 1411 break; 1412 case '5': 1413 fmapp_set_tx_rds_radio_af(cmd+1); 1414 break; 1415 case 'h': 1416 fmapp_display_tx_menu(); 1417 break; 1418 } 1419 } 1420 /* Switch to RX mode before accepting user commands for RX */ 1421 void fmapp_execute_rx_command(void) 1422 { 1423 char cmd[100]; 1424 struct v4l2_tuner vtun; 1425 int ret; 1426 1427 vtun.index = 0; 1428 vtun.audmode = V4L2_TUNER_MODE_STEREO; 1429 vtun.rxsubchans = V4L2_TUNER_SUB_RDS; 1430 ret = ioctl(g_radio_fd, VIDIOC_S_TUNER, &vtun); 1431 if(ret < 0) 1432 { 1433 printf("Failed to set RX mode\n"); 1434 return; 1435 } 1436 1437 printf("Switched to RX menu\n"); 1438 printf("type 'h' for help\n"); 1439 1440 while(1) 1441 { 1442 fgets(cmd, sizeof(cmd), stdin); 1443 switch(cmd[0]) { 1444 case 'g': 1445 fmapp_execute_rx_get_command(cmd+1); 1446 break; 1447 case 'q': 1448 printf("quiting RX menu\n"); 1449 if (pcm_p != NULL && pcm_c != NULL) 1450 fmapp_start_audio(); 1451 return; 1452 default: 1453 fmapp_execute_rx_other_command(cmd); 1454 break; 1455 } 1456 } 1457 } 1458 void fmapp_execute_tx_command(void) 1459 { 1460 char cmd[100]; 1461 struct v4l2_modulator vmod; 1462 int ret; 1463 1464 vmod.index = 0; 1465 vmod.txsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_RDS; 1466 1467 ret = ioctl(g_radio_fd, VIDIOC_S_MODULATOR, &vmod); 1468 if(ret < 0) 1469 { 1470 printf("Failed to set TX mode\n"); 1471 return; 1472 } 1473 1474 printf("Switched to TX menu\n"); 1475 printf("type 'h' for help\n"); 1476 1477 while(1) 1478 { 1479 fgets(cmd, sizeof(cmd), stdin); 1480 switch(cmd[0]) { 1481 case 'g': 1482 fmapp_execute_tx_get_command(cmd+1); 1483 break; 1484 case 'q': 1485 printf("quiting TX menu\n"); 1486 return; 1487 default: 1488 fmapp_execute_tx_other_command(cmd); 1489 break; 1490 } 1491 } 1492 } 1493 1494 int fmapp_read_anddisplay_capabilities(void) 1495 { 1496 struct v4l2_capability cap; 1497 int res; 1498 1499 res = ioctl(g_radio_fd,VIDIOC_QUERYCAP,&cap); 1500 if(res < 0) 1501 { 1502 printf("Failed to read %s capabilities\n",DEFAULT_RADIO_DEVICE); 1503 return res; 1504 } 1505 if((cap.capabilities & V4L2_CAP_RADIO) == 0) 1506 { 1507 printf("%s is not radio devcie",DEFAULT_RADIO_DEVICE); 1508 return -1; 1509 } 1510 printf("\n***%s Info ****\n",DEFAULT_RADIO_DEVICE); 1511 printf("Driver : %s\n",cap.driver); 1512 printf("Card : %s\n",cap.card); 1513 printf("Bus : %s\n",cap.bus_info); 1514 printf("Capabilities : 0x%x\n",cap.capabilities); 1515 1516 return 0; 1517 } 1518 1519 static void sig_handler() 1520 { 1521 if(g_rds_thread_running) 1522 g_rds_thread_terminate = 1; 1523 1524 close(g_radio_fd); 1525 printf("Terminating..\n\n"); 1526 exit(1); 1527 } 1528 int main() 1529 { 1530 char choice[100]; 1531 char exit_flag; 1532 int ret; 1533 struct sigaction sa; 1534 1535 printf("** TI Kernel Space FM Driver Test Application **\n"); 1536 1537 printf("Opening device '%s'\n",DEFAULT_RADIO_DEVICE); 1538 g_radio_fd = open(DEFAULT_RADIO_DEVICE, O_RDWR); 1539 if(g_radio_fd < 0) 1540 { 1541 printf("Unable to open %s \nTerminating..\n",DEFAULT_RADIO_DEVICE); 1542 return 0; 1543 } 1544 ret = fmapp_read_anddisplay_capabilities(); 1545 if(ret< 0) 1546 { 1547 close(g_radio_fd); 1548 return ret; 1549 } 1550 /* to handle ctrl + c and kill signals */ 1551 memset(&sa, 0, sizeof(sa)); 1552 sa.sa_handler = sig_handler; 1553 sigaction(SIGTERM, &sa, NULL); 1554 sigaction(SIGINT, &sa, NULL); 1555 1556 exit_flag = 1; 1557 while(exit_flag) 1558 { 1559 printf("1 FM RX\n"); 1560 printf("2 FM TX\n"); 1561 printf("3 Exit\n"); 1562 fgets(choice, sizeof(choice), stdin); 1563 1564 switch(atoi(choice)) 1565 { 1566 case 1: /* FM RX */ 1567 fmapp_execute_rx_command(); 1568 break; 1569 case 2: /* FM TX */ 1570 fmapp_execute_tx_command(); 1571 break; 1572 case 3: 1573 printf("Terminating..\n\n"); 1574 exit_flag = 0; 1575 break; 1576 default: 1577 printf("Invalid choice , try again\n"); 1578 continue; 1579 } 1580 } 1581 if(g_rds_thread_running) 1582 g_rds_thread_terminate = 1; // Terminate RDS thread 1583 1584 close(g_radio_fd); 1585 return 0; 1586 } 1587 1588 1589