Home | History | Annotate | Download | only in kfmapp
      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