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