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[4]; 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 fm_rssi_threshhold[3] = '\0'; 750 751 printf("Current FM RSSI threshold level is %d \n", 752 atoi((char *) &fm_rssi_threshhold)); 753 754 exit: 755 close(fd); 756 return res; 757 } 758 759 int fmapp_set_rx_rssi_threshold(char *cmd) 760 { 761 int fd, res; 762 763 fd = open(FMRX_RSSI_LVL_SYSFS_ENTRY, O_RDWR); 764 if (fd < 0) { 765 printf("Can't open %s", FMRX_RSSI_LVL_SYSFS_ENTRY); 766 return -1; 767 } 768 769 res = write(fd, cmd, sizeof(char) * 3); 770 if(res <= 0){ 771 printf("Failed to set FM RSSI threshold level\n"); 772 goto exit; 773 } 774 775 printf("FM RSSI threshold level is set to %d\n", atoi(cmd)); 776 777 exit: 778 close(fd); 779 return res; 780 } 781 782 int fmapp_set_band(char *cmd) 783 { 784 int fd, res; 785 786 fd = open(FMRX_BAND_SYSFS_ENTRY, O_RDWR); 787 if (fd < 0) { 788 printf("Can't open %s", FMRX_BAND_SYSFS_ENTRY); 789 return -1; 790 } 791 792 res = write(fd, cmd, sizeof(char)); 793 if(res <= 0){ 794 printf("Failed to set FM Band\n"); 795 goto exit; 796 } 797 798 printf("FM Band is set to %s\n", atoi(cmd) == 0?"US/EUROPE":"JAPAN"); 799 exit: 800 close(fd); 801 return res; 802 } 803 804 int fmapp_get_band(void) 805 { 806 unsigned char fm_band; 807 int fd, res; 808 809 fd = open(FMRX_BAND_SYSFS_ENTRY, O_RDONLY); 810 if (fd < 0) { 811 printf("Can't open %s", FMRX_BAND_SYSFS_ENTRY); 812 return -1; 813 } 814 815 res = read(fd, &fm_band, 1); 816 if(res < 0){ 817 printf("reading %s failed %s\n",FMRX_BAND_SYSFS_ENTRY,strerror(res)); 818 goto exit; 819 } 820 821 printf("Present FM Band is %s \n", 822 (atoi((char *) &fm_band)) == 0?"US/EUROPE":"JAPAN"); 823 exit: 824 close(fd); 825 return res; 826 } 827 static void tinymix_set_value(struct mixer *mixer, unsigned int id, 828 int value) 829 { 830 struct mixer_ctl *ctl; 831 enum mixer_ctl_type type; 832 unsigned int i, num_values; 833 834 ctl = mixer_get_ctl(mixer, id); 835 type = mixer_ctl_get_type(ctl); 836 num_values = mixer_ctl_get_num_values(ctl); 837 838 for(i=0; i<num_values; i++) { 839 if (mixer_ctl_set_value(ctl, i, value)) { 840 fprintf(stderr, "Error: invalid value\n"); 841 return; 842 } 843 } 844 } 845 846 int fmapp_start_audio() 847 { 848 struct pcm_config config; 849 850 mixer = mixer_open(0); 851 if (!mixer) { 852 fprintf(stderr, "Failed to open mixer\n"); 853 return EXIT_FAILURE; 854 } 855 856 config.channels = 2; 857 config.rate = 48000; 858 config.period_size = 1024; 859 config.period_count = 4; 860 config.format = PCM_FORMAT_S16_LE; 861 config.silence_threshold = 0; 862 config.stop_threshold = -1; 863 864 if (fm_aud_enable == 0){ 865 /* Set Tinymix controles */ 866 tinymix_set_value(mixer, 77, 2); 867 tinymix_set_value(mixer, 76, 2); 868 tinymix_set_value(mixer, 64, 1); 869 tinymix_set_value(mixer, 65, 4); 870 tinymix_set_value(mixer, 55, 12); 871 tinymix_set_value(mixer, 54, 11); 872 tinymix_set_value(mixer, 51, 1); 873 tinymix_set_value(mixer, 9, 120); 874 tinymix_set_value(mixer, 72, 1); 875 tinymix_set_value(mixer, 73, 1); 876 tinymix_set_value(mixer, 34, 1); 877 tinymix_set_value(mixer, 50, 1); 878 879 pcm_p = pcm_open(0, pdevice, PCM_OUT, &config); 880 if (!pcm_p || !pcm_is_ready(pcm_p)) { 881 fprintf(stderr, "Unable to open PCM device (%s)\n", 882 pcm_get_error(pcm_p)); 883 return 0; 884 } 885 printf("Playback device opened successfully"); 886 pcm_c = pcm_open(0, cdevice, PCM_IN, &config); 887 if (!pcm_c || !pcm_is_ready(pcm_c)) { 888 fprintf(stderr, "Unable to open PCM device (%s)\n", 889 pcm_get_error(pcm_c)); 890 return 0; 891 } 892 printf("Capture device opened successfully"); 893 pcm_start(pcm_c); 894 pcm_start(pcm_p); 895 printf(" Trigered the loopback"); 896 fm_aud_enable = 1; 897 } 898 else { 899 /* Set Tinymix controls to Normal*/ 900 tinymix_set_value(mixer, 77, 0); 901 tinymix_set_value(mixer, 76, 0); 902 tinymix_set_value(mixer, 64, 0); 903 tinymix_set_value(mixer, 65, 0); 904 tinymix_set_value(mixer, 55, 0); 905 tinymix_set_value(mixer, 54, 0); 906 tinymix_set_value(mixer, 51, 0); 907 tinymix_set_value(mixer, 9, 0); 908 tinymix_set_value(mixer, 72, 0); 909 tinymix_set_value(mixer, 73, 0); 910 tinymix_set_value(mixer, 34, 0); 911 tinymix_set_value(mixer, 50, 0); 912 913 /* close the device */ 914 pcm_stop(pcm_p); 915 pcm_stop(pcm_c); 916 pcm_close(pcm_p); 917 pcm_close(pcm_c); 918 fm_aud_enable = 0; 919 } 920 printf("FM RX Audio Routing Done\n"); 921 return 0; 922 } 923 924 int fmapp_get_rx_rssi_lvl(void) 925 { 926 struct v4l2_tuner vtun; 927 float rssi_lvl; 928 int res; 929 930 vtun.index = 0; 931 res = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); 932 if(res < 0) 933 { 934 printf("Failed to get tunner attributes\n"); 935 return res; 936 } 937 rssi_lvl = ((float)vtun.signal / 0xFFFF) * 100; 938 printf("Signal Strength: %d%%\n",(unsigned int)rssi_lvl); 939 940 return 0; 941 } 942 int fmapp_set_stereo_mono_mode(void) 943 { 944 struct v4l2_tuner vtun; 945 int res = 0; 946 947 vtun.index = 0; 948 res = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); 949 if(res < 0) 950 { 951 printf("Failed to set stereo-mono mode\n"); 952 return res; 953 } 954 955 if(V4L2_TUNER_MODE_STEREO == vtun.audmode) 956 vtun.audmode = V4L2_TUNER_MODE_MONO; 957 else 958 vtun.audmode = V4L2_TUNER_MODE_STEREO; 959 960 res = ioctl(g_radio_fd, VIDIOC_S_TUNER, &vtun); 961 if(res < 0) 962 { 963 printf("Failed to set stereo-mono mode\n"); 964 return res; 965 } 966 printf("Audio Mode set to: %s\n",(vtun.audmode == V4L2_TUNER_MODE_STEREO) ? "STEREO":"MONO"); 967 968 return 0; 969 } 970 int fmapp_get_stereo_mono_mode(void) 971 { 972 struct v4l2_tuner vtun; 973 int res; 974 975 vtun.index = 0; 976 res = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); 977 if(res < 0) 978 { 979 printf("Failed to get tunner attributes\n"); 980 return res; 981 } 982 printf("Audio Mode: %s\n",(vtun.audmode == V4L2_TUNER_MODE_STEREO) ? "STEREO":"MONO"); 983 984 return 0; 985 } 986 int fmapp_get_rx_tunner_attributes(void) 987 { 988 struct v4l2_tuner vtun; 989 float sigstrength_percentage; 990 int res; 991 992 vtun.index = 0; 993 res = ioctl(g_radio_fd,VIDIOC_G_TUNER,&vtun); 994 if(res < 0) 995 { 996 printf("Failed to get tunner attributes\n"); 997 return res; 998 } 999 printf("-----------------------\n"); 1000 printf("Tuner Name: %s\n",vtun.name); 1001 /* TODO: FM driver is not setting V4L2_TUNER_CAP_LOW flag , but its returning vtun.rangelow 1002 * and vtun.rangehigh ranges in HZ . This needs to be corrected in FM driver */ 1003 printf(" Low Freq: %d KHz\n", 1004 (unsigned int )((float)vtun.rangelow * 0.0625)); 1005 printf(" High Freq: %d KHz\n", 1006 (unsigned int) ((float)vtun.rangehigh * 0.0625)); 1007 printf("Audio Mode: %s\n",(vtun.audmode == V4L2_TUNER_MODE_STEREO) ? "STEREO":"MONO"); 1008 sigstrength_percentage = ((float)vtun.signal /0xFFFF) * 100; 1009 printf("Signal Strength: %d%%\n",(unsigned int)sigstrength_percentage); 1010 printf("-----------------------\n"); 1011 return 0; 1012 } 1013 1014 int fmapp_get_scan_valid_frequencies(void) 1015 { 1016 int ret; 1017 struct v4l2_tuner vtun; 1018 struct v4l2_frequency vf; 1019 struct v4l2_control vctrl; 1020 float freq_multiplicator,start_frq,end_frq, 1021 freq,perc,threshold,divide_by; 1022 long totsig; 1023 unsigned char index; 1024 1025 vtun.index = 0; 1026 ret = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); /* get frequency range */ 1027 if (ret < 0) { 1028 printf("Failed to get frequency range"); 1029 return ret; 1030 } 1031 freq_multiplicator = (62.5 * ((vtun.capability & V4L2_TUNER_CAP_LOW) 1032 ? 1 : 1000)); 1033 1034 divide_by = (vtun.capability & V4L2_TUNER_CAP_LOW) ? 1000000 : 1000; 1035 start_frq = ((float)vtun.rangelow * freq_multiplicator)/divide_by; 1036 end_frq = ((float)vtun.rangehigh * freq_multiplicator)/divide_by; 1037 1038 threshold = FMAPP_ASCAN_SIGNAL_THRESHOLD_PER; 1039 1040 /* Enable Mute */ 1041 vctrl.id = V4L2_CID_AUDIO_MUTE; 1042 vctrl.value = FM_MUTE_ON; 1043 ret = ioctl(g_radio_fd,VIDIOC_S_CTRL,&vctrl); 1044 if(ret < 0) 1045 { 1046 printf("Failed to set mute mode\n"); 1047 return ret; 1048 } 1049 printf("Auto Scanning..\n"); 1050 for(freq=start_frq;freq<=end_frq;freq+=0.1) 1051 { 1052 vf.tuner = 0; 1053 vf.frequency = rint(freq*1000); 1054 ret = ioctl(g_radio_fd, VIDIOC_S_FREQUENCY, &vf); /* tune */ 1055 if (ret < 0) { 1056 printf("failed to set freq"); 1057 return ret; 1058 } 1059 totsig = 0; 1060 for(index=0;index<FMAPP_ASCAN_NO_OF_SIGNAL_SAMPLE;index++) 1061 { 1062 vtun.index = 0; 1063 ret = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); /* get info */ 1064 if (ret < 0) { 1065 printf("Failed to get frequency range"); 1066 return ret; 1067 } 1068 totsig += vtun.signal; 1069 perc = (totsig / (65535.0 * index)); 1070 usleep(1); 1071 } 1072 perc = (totsig / (65535.0 * FMAPP_ASCAN_NO_OF_SIGNAL_SAMPLE)); 1073 if ((perc*100.0) > threshold) 1074 printf("%2.1f MHz(%d%%)\n",freq,((unsigned short)(perc * 100.0))); 1075 } 1076 /* Disable Mute */ 1077 vctrl.id = V4L2_CID_AUDIO_MUTE; 1078 vctrl.value = FM_MUTE_OFF; 1079 ret = ioctl(g_radio_fd,VIDIOC_S_CTRL,&vctrl); 1080 if(ret < 0) 1081 { 1082 printf("Failed to set mute mode\n"); 1083 return ret; 1084 } 1085 printf("Scan Completed\n"); 1086 return 0; 1087 } 1088 int fmapp_get_rds_onoff(void) 1089 { 1090 struct v4l2_tuner vtun; 1091 int res = 0; 1092 1093 vtun.index = 0; 1094 res = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); 1095 if(res < 0) 1096 { 1097 printf("Failed to read RDS state\n"); 1098 return res; 1099 } 1100 printf("RDS is: %s\n",(vtun.rxsubchans & V4L2_TUNER_SUB_RDS) ? "ON":"OFF"); 1101 1102 return 0; 1103 } 1104 void fmapp_rds_decode(int blkno, int byte1, int byte2) 1105 { 1106 static char rds_psn[9]; 1107 static char rds_txt[65]; 1108 static int rds_pty,ms_code; 1109 static int group,spare,blkc_byte1,blkc_byte2; 1110 1111 switch (blkno) { 1112 case 0: /* Block A */ 1113 printf("----------------------------------------\n"); 1114 printf("block A - id=%d\n",(byte1 << 8) | byte2); 1115 break; 1116 case 1: /* Block B */ 1117 printf("block B - group=%d%c tp=%d pty=%d spare=%d\n", 1118 (byte1 >> 4) & 0x0f, 1119 ((byte1 >> 3) & 0x01) + 'A', 1120 (byte1 >> 2) & 0x01, 1121 ((byte1 << 3) & 0x18) | ((byte2 >> 5) & 0x07), 1122 byte2 & 0x1f); 1123 group = (byte1 >> 3) & 0x1f; 1124 spare = byte2 & 0x1f; 1125 rds_pty = ((byte1 << 3) & 0x18) | ((byte2 >> 5) & 0x07); 1126 ms_code = (byte2 >> 3)& 0x1; 1127 break; 1128 case 2: /* Block C */ 1129 printf("block C - 0x%02x 0x%02x\n",byte1,byte2); 1130 blkc_byte1 = byte1; 1131 blkc_byte2 = byte2; 1132 break; 1133 case 3 : /* Block D */ 1134 printf("block D - 0x%02x 0x%02x\n",byte1,byte2); 1135 switch (group) { 1136 case 0: /* Group 0A */ 1137 rds_psn[2*(spare & 0x03)+0] = byte1; 1138 rds_psn[2*(spare & 0x03)+1] = byte2; 1139 if ((spare & 0x03) == 0x03) 1140 printf("PSN: %s, PTY: %s, MS: %s\n",rds_psn, 1141 pty_str[rds_pty],ms_code?"Music":"Speech"); 1142 break; 1143 case 4: /* Group 2A */ 1144 rds_txt[4*(spare & 0x0f)+0] = blkc_byte1; 1145 rds_txt[4*(spare & 0x0f)+1] = blkc_byte2; 1146 rds_txt[4*(spare & 0x0f)+2] = byte1; 1147 rds_txt[4*(spare & 0x0f)+3] = byte2; 1148 /* Display radio text once we get 16 characters */ 1149 // if ((spare & 0x0f) == 0x0f) 1150 if (spare > 16) 1151 { 1152 printf("Radio Text: %s\n",rds_txt); 1153 // memset(&rds_txt,0,sizeof(rds_txt)); 1154 } 1155 break; 1156 } 1157 printf("----------------------------------------\n"); 1158 break; 1159 default: 1160 printf("unknown block [%d]\n",blkno); 1161 } 1162 } 1163 void *rds_thread(void *data) 1164 { 1165 unsigned char buf[600]; 1166 int radio_fd; 1167 int ret,index; 1168 struct pollfd pfd; 1169 1170 radio_fd = (int)data; 1171 1172 while(!g_rds_thread_terminate) 1173 { 1174 while(1){ 1175 memset(&pfd, 0, sizeof(pfd)); 1176 pfd.fd = radio_fd; 1177 pfd.events = POLLIN; 1178 ret = poll(&pfd, 1, 10); 1179 if (ret == 0){ 1180 /* Break the poll after RDS data available */ 1181 break; 1182 } 1183 } 1184 1185 ret = read(radio_fd,buf,500); 1186 if(ret < 0) { 1187 1188 break; 1189 } 1190 else if( ret > 0) 1191 { 1192 for(index=0;index<ret;index+=3) 1193 fmapp_rds_decode(buf[index+2] & 0x7,buf[index+1],buf[index]); 1194 } 1195 } 1196 /* TODO: Need to conform thread termination. 1197 * below msg is not coming ,have a doubt on thread termination. 1198 * Fix this later. */ 1199 printf("RDS thread exiting..\n"); 1200 return NULL; 1201 } 1202 int fmapp_set_rds_onoff(unsigned char fmapp_mode) 1203 { 1204 struct v4l2_tuner vtun; 1205 int ret; 1206 static unsigned char rds_mode = FM_RDS_DISABLE; 1207 1208 vtun.index = 0; 1209 ret = ioctl(g_radio_fd, VIDIOC_G_TUNER, &vtun); 1210 if(ret < 0) 1211 { 1212 printf("Failed to get tuner capabilities\n"); 1213 return ret; 1214 } 1215 if(rds_mode == FM_RDS_DISABLE) { 1216 vtun.rxsubchans |= V4L2_TUNER_SUB_RDS; 1217 rds_mode = FM_RDS_ENABLE; 1218 } else { 1219 vtun.rxsubchans &= ~V4L2_TUNER_SUB_RDS; 1220 rds_mode = FM_RDS_DISABLE; 1221 } 1222 1223 ret = ioctl(g_radio_fd, VIDIOC_S_TUNER, &vtun); 1224 if(ret < 0) 1225 { 1226 printf("Failed to set rds on/off status\n"); 1227 return ret; 1228 } 1229 /* Create rds receive thread once */ 1230 if(fmapp_mode == FM_MODE_RX && rds_mode == FM_RDS_ENABLE && 1231 g_rds_thread_running == 0) 1232 { 1233 g_rds_thread_running = 1; 1234 pthread_create(&g_rds_thread_ptr,NULL,rds_thread,(void *)g_radio_fd); 1235 } 1236 1237 printf("RDS %s\n",g_rds_modes[rds_mode]); 1238 return 0; 1239 } 1240 1241 void fmapp_execute_tx_get_command(char *cmd) 1242 { 1243 switch(cmd[0]) 1244 { 1245 case 'f': 1246 fmapp_get_tx_frequency(); 1247 break; 1248 case 'e': 1249 fmapp_get_premphasis_filter_mode(); 1250 break; 1251 case 'p': 1252 fmapp_get_tx_power_level(); 1253 break; 1254 case 'i': 1255 fmapp_get_tx_ant_imp(); 1256 break; 1257 default: 1258 printf("unknown command; type 'h' for help\n"); 1259 } 1260 1261 } 1262 void fmapp_execute_rx_get_command(char *cmd) 1263 { 1264 switch(cmd[0]) 1265 { 1266 case 'f': 1267 fmapp_get_rx_frequency(); 1268 break; 1269 case 'r': 1270 fmapp_get_rx_rssi_lvl(); 1271 break; 1272 case 't': 1273 fmapp_get_rds_onoff(); 1274 break; 1275 case 'v': 1276 fmapp_get_rx_volume(); 1277 break; 1278 case 'm': 1279 fmapp_get_rx_mute_mode(); 1280 break; 1281 case 'b': 1282 fmapp_get_band(); 1283 break; 1284 case 'c': 1285 fmapp_get_rx_af_switch(); 1286 break; 1287 case '?': 1288 fmapp_get_rx_rssi_threshold(); 1289 break; 1290 #if 0 1291 case 'd': 1292 fmapp_get_rfmute(fm_snd_ctrl); 1293 break; 1294 case 'z': 1295 fmapp_get_rds_operation_mode(fm_snd_ctrl); 1296 break; 1297 #endif 1298 case 's': 1299 fmapp_get_stereo_mono_mode(); 1300 break; 1301 #if 0 1302 case 'e': 1303 fmapp_get_rx_deemphasis_filter_mode(fm_snd_ctrl); 1304 break; 1305 #endif 1306 case 'a': 1307 fmapp_get_rx_tunner_attributes(); 1308 break; 1309 #if 0 1310 case 'n': 1311 fmapp_get_scan_valid_frequencies(); 1312 break; 1313 #endif 1314 default: 1315 printf("unknown command; type 'h' for help\n"); 1316 } 1317 } 1318 void fmapp_execute_rx_other_command(char *cmd) 1319 { 1320 switch(cmd[0]) 1321 { 1322 #if 0 1323 case 'p': 1324 fmapp_change_rx_power_mode(fm_snd_ctrl); 1325 break; 1326 #endif 1327 case 'f': 1328 fmapp_set_rx_frequency(cmd+1); 1329 break; 1330 case 't': 1331 fmapp_set_rds_onoff(FM_MODE_RX); 1332 break; 1333 case '+': 1334 fmapp_rx_increase_volume(); 1335 break; 1336 case '-': 1337 fmapp_rx_decrease_volume(); 1338 break; 1339 case 'v': 1340 fmapp_set_rx_volume(cmd+1,FMAPP_INTERACTIVE,0); 1341 break; 1342 case 'm': 1343 fmapp_set_rx_mute_mode(); 1344 break; 1345 case '<': 1346 fmapp_rx_seek(FM_SEARCH_DIRECTION_DOWN); 1347 break; 1348 case '>': 1349 fmapp_rx_seek(FM_SEARCH_DIRECTION_UP); 1350 break; 1351 case 'b': 1352 fmapp_set_band(cmd+1); 1353 break; 1354 case 'h': 1355 fmapp_display_rx_menu(); 1356 break; 1357 case 'c': 1358 fmapp_set_rx_af_switch(cmd+1); 1359 break; 1360 case '?': 1361 fmapp_set_rx_rssi_threshold(cmd+1); 1362 break; 1363 #if 0 1364 case 'd': 1365 fmapp_set_rfmute(fm_snd_ctrl); 1366 break; 1367 case 'z': 1368 fmapp_set_rds_operation_mode(fm_snd_ctrl); 1369 break; 1370 #endif 1371 case 's': 1372 fmapp_set_stereo_mono_mode(); 1373 break; 1374 #if 0 1375 case 'e': 1376 fmapp_set_rx_deemphasis_filter_mode(fm_snd_ctrl); 1377 break; 1378 #endif 1379 case 'A': 1380 fmapp_start_audio(); 1381 break; 1382 } 1383 } 1384 1385 void fmapp_execute_tx_other_command(char *cmd) 1386 { 1387 switch(cmd[0]) 1388 { 1389 case 'f': 1390 fmapp_set_tx_frequency(cmd+1); 1391 break; 1392 case 'e': 1393 fmapp_set_premphasis_filter_mode(cmd+1); 1394 break; 1395 case 'p': 1396 fmapp_set_tx_power_level(cmd+1); 1397 break; 1398 case 'i': 1399 fmapp_set_tx_ant_imp(cmd+1); 1400 break; 1401 case '1': 1402 fmapp_set_tx_rds_radio_text(); 1403 break; 1404 case '2': 1405 fmapp_set_tx_rds_radio_ps_name(); 1406 break; 1407 case '3': 1408 fmapp_set_tx_rds_radio_pi_code(cmd+1); 1409 break; 1410 case '4': 1411 fmapp_set_tx_rds_radio_pty(cmd+1); 1412 break; 1413 case '5': 1414 fmapp_set_tx_rds_radio_af(cmd+1); 1415 break; 1416 case 'h': 1417 fmapp_display_tx_menu(); 1418 break; 1419 } 1420 } 1421 /* Switch to RX mode before accepting user commands for RX */ 1422 void fmapp_execute_rx_command(void) 1423 { 1424 char cmd[100]; 1425 struct v4l2_tuner vtun; 1426 int ret; 1427 1428 vtun.index = 0; 1429 vtun.audmode = V4L2_TUNER_MODE_STEREO; 1430 vtun.rxsubchans = V4L2_TUNER_SUB_RDS; 1431 ret = ioctl(g_radio_fd, VIDIOC_S_TUNER, &vtun); 1432 if(ret < 0) 1433 { 1434 printf("Failed to set RX mode\n"); 1435 return; 1436 } 1437 1438 printf("Switched to RX menu\n"); 1439 printf("type 'h' for help\n"); 1440 1441 while(1) 1442 { 1443 fgets(cmd, sizeof(cmd), stdin); 1444 switch(cmd[0]) { 1445 case 'g': 1446 fmapp_execute_rx_get_command(cmd+1); 1447 break; 1448 case 'q': 1449 printf("quiting RX menu\n"); 1450 if (pcm_p != NULL && pcm_c != NULL) 1451 fmapp_start_audio(); 1452 return; 1453 default: 1454 fmapp_execute_rx_other_command(cmd); 1455 break; 1456 } 1457 } 1458 } 1459 void fmapp_execute_tx_command(void) 1460 { 1461 char cmd[100]; 1462 struct v4l2_modulator vmod; 1463 int ret; 1464 1465 vmod.index = 0; 1466 vmod.txsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_RDS; 1467 1468 ret = ioctl(g_radio_fd, VIDIOC_S_MODULATOR, &vmod); 1469 if(ret < 0) 1470 { 1471 printf("Failed to set TX mode\n"); 1472 return; 1473 } 1474 1475 printf("Switched to TX menu\n"); 1476 printf("type 'h' for help\n"); 1477 1478 while(1) 1479 { 1480 fgets(cmd, sizeof(cmd), stdin); 1481 switch(cmd[0]) { 1482 case 'g': 1483 fmapp_execute_tx_get_command(cmd+1); 1484 break; 1485 case 'q': 1486 printf("quiting TX menu\n"); 1487 return; 1488 default: 1489 fmapp_execute_tx_other_command(cmd); 1490 break; 1491 } 1492 } 1493 } 1494 1495 int fmapp_read_anddisplay_capabilities(void) 1496 { 1497 struct v4l2_capability cap; 1498 int res; 1499 1500 res = ioctl(g_radio_fd,VIDIOC_QUERYCAP,&cap); 1501 if(res < 0) 1502 { 1503 printf("Failed to read %s capabilities\n",DEFAULT_RADIO_DEVICE); 1504 return res; 1505 } 1506 if((cap.capabilities & V4L2_CAP_RADIO) == 0) 1507 { 1508 printf("%s is not radio devcie",DEFAULT_RADIO_DEVICE); 1509 return -1; 1510 } 1511 printf("\n***%s Info ****\n",DEFAULT_RADIO_DEVICE); 1512 printf("Driver : %s\n",cap.driver); 1513 printf("Card : %s\n",cap.card); 1514 printf("Bus : %s\n",cap.bus_info); 1515 printf("Capabilities : 0x%x\n",cap.capabilities); 1516 1517 return 0; 1518 } 1519 1520 static void sig_handler() 1521 { 1522 if(g_rds_thread_running) 1523 g_rds_thread_terminate = 1; 1524 1525 close(g_radio_fd); 1526 printf("Terminating..\n\n"); 1527 exit(1); 1528 } 1529 int main() 1530 { 1531 char choice[100]; 1532 char exit_flag; 1533 int ret; 1534 struct sigaction sa; 1535 1536 printf("** TI Kernel Space FM Driver Test Application **\n"); 1537 1538 printf("Opening device '%s'\n",DEFAULT_RADIO_DEVICE); 1539 g_radio_fd = open(DEFAULT_RADIO_DEVICE, O_RDWR); 1540 if(g_radio_fd < 0) 1541 { 1542 printf("Unable to open %s \nTerminating..\n",DEFAULT_RADIO_DEVICE); 1543 return 0; 1544 } 1545 ret = fmapp_read_anddisplay_capabilities(); 1546 if(ret< 0) 1547 { 1548 close(g_radio_fd); 1549 return ret; 1550 } 1551 /* to handle ctrl + c and kill signals */ 1552 memset(&sa, 0, sizeof(sa)); 1553 sa.sa_handler = sig_handler; 1554 sigaction(SIGTERM, &sa, NULL); 1555 sigaction(SIGINT, &sa, NULL); 1556 1557 exit_flag = 1; 1558 while(exit_flag) 1559 { 1560 printf("1 FM RX\n"); 1561 printf("2 FM TX\n"); 1562 printf("3 Exit\n"); 1563 fgets(choice, sizeof(choice), stdin); 1564 1565 switch(atoi(choice)) 1566 { 1567 case 1: /* FM RX */ 1568 fmapp_execute_rx_command(); 1569 break; 1570 case 2: /* FM TX */ 1571 fmapp_execute_tx_command(); 1572 break; 1573 case 3: 1574 printf("Terminating..\n\n"); 1575 exit_flag = 0; 1576 break; 1577 default: 1578 printf("Invalid choice , try again\n"); 1579 continue; 1580 } 1581 } 1582 if(g_rds_thread_running) 1583 g_rds_thread_terminate = 1; // Terminate RDS thread 1584 1585 close(g_radio_fd); 1586 return 0; 1587 } 1588 1589 1590