C++程序  |  2259行  |  71.57 KB

/*
 *
 * Copyright 2001-2011 Texas Instruments, Inc. - http://www.ti.com/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "android_runtime/AndroidRuntime.h"
#include "jni.h"
#include "JNIHelp.h"
#include "v4l2_JbtlLog.h"


#define LOG_TAG "JFmRxNative"
#include <cutils/properties.h>

using namespace android;

extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <asoundlib.h>
#include <linux/videodev.h>
#include <math.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <poll.h>

#include "JFmRxNative.h"

/*Callback for FM commands*/
void nativeJFmRx_Callback(long context, int status,
            int command, long value);

 /*Callback for FM  PS*/


   void nativeJFmRx_PS_Callback(long context,int status, int freq,
               int len,unsigned char * name,
               int repertoire) ;

/*Callback for FM  Radio Text*/

void nativeJFmRx_RadioText_Callback(int status, bool resetDisplay,
            unsigned char * msg, int len, int startIndex,
            int repertoire) ;
} //extern "C"

static JavaVM *g_jVM = NULL;
static jclass _sJClass;

typedef pthread_t       THREAD_HANDLE;
THREAD_HANDLE   p_threadHandle;         /* Thread Handle for RDS data  */
static bool isThreadCreated = false;
static int radio_fd;
//snd_ctl_t *fm_snd_ctrl;
long jContext;
volatile bool g_stopCommListener = false;

static int chanl_spacing=200000;

/* Complete parsing of the RDS data has not been implemented yet
Commented the FM RX RDS callbacks functionality start*/

#if 0
static jmethodID _sMethodId_nativeCb_fmRxRawRDS;
static jmethodID _sMethodId_nativeCb_fmRxPiCodeChanged;
static jmethodID _sMethodId_nativeCb_fmRxPtyCodeChanged;
static jmethodID _sMethodId_nativeCb_fmRxMonoStereoModeChanged;
static jmethodID _sMethodId_nativeCb_fmRxAudioPathChanged;
static jmethodID _sMethodId_nativeCb_fmRxAfSwitchFreqFailed;
static jmethodID _sMethodId_nativeCb_fmRxAfSwitchStart;
static jmethodID _sMethodId_nativeCb_fmRxAfSwitchComplete;
static jmethodID _sMethodId_nativeCb_fmRxAfListChanged;
static jmethodID _sMethodId_nativeCb_fmRxCompleteScanDone;
#endif

/*Commented the FM RX RDS callbacks functionality end*/


static jmethodID _sMethodId_nativeCb_fmRxPsChanged;
static jmethodID _sMethodId_nativeCb_fmRxRadioText;
static jmethodID _sMethodId_nativeCb_fmRxCmdEnable;
static jmethodID _sMethodId_nativeCb_fmRxCmdDisable;

static jmethodID _sMethodId_nativeCb_fmRxCmdEnableAudio;
static jmethodID _sMethodId_nativeCb_fmRxCmdChangeAudioTarget;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetBand;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetBand;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetMonoStereoMode;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetMonoStereoMode;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetMuteMode;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetMuteMode;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetRfDependentMuteMode;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetRfDependentMuteMode;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetRssiThreshhold;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetRssiThreshhold;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetDeemphasisFilter;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetDeemphasisFilter;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetVolume;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetVolume;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetChannelSpacing;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetChannelSpacing;
static jmethodID _sMethodId_nativeCb_fmRxCmdTune;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetTunedFrequency;
static jmethodID _sMethodId_nativeCb_fmRxCmdSeek;
static jmethodID _sMethodId_nativeCb_fmRxCmdStopSeek;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetRssi;
static jmethodID _sMethodId_nativeCb_fmRxCmdEnableRds;
static jmethodID _sMethodId_nativeCb_fmRxCmdDisableRds;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetRdsSystem;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetRdsSystem;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetRdsGroupMask;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetRdsGroupMask;
static jmethodID _sMethodId_nativeCb_fmRxCmdSetRdsAfSwitchMode;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetRdsAfSwitchMode;
static jmethodID _sMethodId_nativeCb_fmRxCmdDisableAudio;
static jmethodID _sMethodId_nativeCb_fmRxCmdDestroy;
static jmethodID _sMethodId_nativeCb_fmRxCmdChangeDigitalAudioConfiguration;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetFwVersion;
static jmethodID _sMethodId_nativeCb_fmRxCmdIsValidChannel;
static jmethodID _sMethodId_nativeCb_fmRxCmdGetCompleteScanProgress;
static jmethodID _sMethodId_nativeCb_fmRxCmdStopCompleteScan;





int rdsParseFunc_updateRepertoire(int byte1,int byte2)
{

    int repertoire1,repertoire2;
    int repertoire3,repertoire4;
    int repertoire;

    /*replace to nibble high/low*/
    repertoire1 =  (FMC_U8)(byte1&RDS_BIT_0_TO_BIT_3);
    repertoire2 =  (FMC_U8)((byte1&RDS_BIT_4_TO_BIT_7)>>4);
    repertoire3 =  (FMC_U8)(byte2&RDS_BIT_0_TO_BIT_3);
    repertoire4 =  (FMC_U8)((byte2&RDS_BIT_4_TO_BIT_7)>>4);

    if((repertoire2==0)&&(repertoire1==15)&&(repertoire4==0)&&(repertoire3==15))
    {
        repertoire = FMC_RDS_REPERTOIRE_G0_CODE_TABLE;

    }
    else if((repertoire2==0)&&(repertoire1==14)&&(repertoire4==0)&&(repertoire3==14))
    {
        repertoire = FMC_RDS_REPERTOIRE_G1_CODE_TABLE;

    }
    else if ((repertoire2==1)&&(repertoire1==11)&&(repertoire4==6)&&(repertoire3==14))
    {
        repertoire = FMC_RDS_REPERTOIRE_G2_CODE_TABLE;

    }

V4L2_JBTL_LOGD(" rdsParseFunc_updateRepertoire repertoire%d\n",repertoire);
    return repertoire;
}


void rds_decode(int blkno, int byte1, int byte2)
{
    static unsigned char rds_psn[9];
    static unsigned  char rds_txt[65];
    static int  rds_pty,ms_code;
    static int group,spare,blkc_byte1,blkc_byte2;
    int len;
    bool resetDisplay =false;
    int status = 0,startIndex=0,repertoire,freq;

    switch (blkno) {
    case 0: /* Block A */
        V4L2_JBTL_LOGD("block A - id=%d\n",(byte1 << 8) | byte2);
    break;
    case 1: /* Block B */
    V4L2_JBTL_LOGD("block B - group=%d%c tp=%d pty=%d spare=%d\n",
            (byte1 >> 4) & 0x0f,
            ((byte1 >> 3) & 0x01) + 'A',
            (byte1 >> 2) & 0x01,
            ((byte1 << 3) & 0x18) | ((byte2 >> 5) & 0x07),
            byte2 & 0x1f);
    group = (byte1 >> 3) & 0x1f;
    spare = byte2 & 0x1f;
    rds_pty = ((byte1 << 3) & 0x18) | ((byte2 >> 5) & 0x07);
        ms_code = (byte2 >> 3)& 0x1;

    break;
    case 2: /* Block C */
        V4L2_JBTL_LOGD("block C - 0x%02x 0x%02x\n",byte1,byte2);
    blkc_byte1 = byte1;
    blkc_byte2 = byte2;
    break;
    case 3 : /* Block D */
    V4L2_JBTL_LOGD("block D - 0x%02x 0x%02x\n",byte1,byte2);
    switch (group) {
    case 0: /* Group 0A */
        rds_psn[2*(spare & 0x03)+0] = byte1;
        rds_psn[2*(spare & 0x03)+1] = byte2;
        if ((spare & 0x03) == 0x03)
        {
            V4L2_JBTL_LOGD("PSN: %s, PTY: %d, MS: %s\n",rds_psn,
                            rds_pty,ms_code?"Music":"Speech");

        len = strlen((const char *)rds_psn);
 V4L2_JBTL_LOGD("PS len %d",len);
        nativeJFmRx_PS_Callback(jContext,status,freq,len,rds_psn,repertoire);
        }

        break;
    case 4: /* Group 2A */

        repertoire = rdsParseFunc_updateRepertoire(byte1,byte2);

        repertoire =0;

 V4L2_JBTL_LOGD("Radio repertoire: %d\n",repertoire);
        rds_txt[4*(spare & 0x0f)+0] = blkc_byte1;
        rds_txt[4*(spare & 0x0f)+1] = blkc_byte2;
        rds_txt[4*(spare & 0x0f)+2] = byte1;
        rds_txt[4*(spare & 0x0f)+3] = byte2;
            /* Display radio text once we get 16 characters */
        if (spare > 16)
            {
            len =strlen((const char *)rds_txt);

 V4L2_JBTL_LOGD("RDS len %d",len);
            V4L2_JBTL_LOGD("Radio Text: %s\n",rds_txt);

            nativeJFmRx_RadioText_Callback(status, resetDisplay,
            rds_txt, len, startIndex,repertoire) ;
            }
        break;
         }
         V4L2_JBTL_LOGD("----------------------------------------\n");
         break;
     default:
         V4L2_JBTL_LOGD("unknown block [%d]\n",blkno);
    }
}

/**
 * Function:        entryFunctionForRdsThread
 * Brief:           Creates a thread for waiting on responses from RDS .
 * Description:
 */

void *entryFunctionForRdsThread(void *data)
{
  unsigned char buf[600];
  int radio_fd;
  int ret,index;
  struct pollfd pfd;

  radio_fd = (int)data;

  V4L2_JBTL_LOGD(" entryFunctionForRdsThread: Entering.g_stopCommListener %d \n",g_stopCommListener);

  while(!g_stopCommListener)
  {

  V4L2_JBTL_LOGD("RDS thread running..\n");

  while(1){
      memset(&pfd, 0, sizeof(pfd));
      pfd.fd = radio_fd;
      pfd.events = POLLIN;
      ret = poll(&pfd, 1, 10);
      if (ret == 0){
          /* Break the poll after RDS data available */
          break;
      }
  }

    ret = read(radio_fd,buf,500);
    if(ret < 0)
    {  V4L2_JBTL_LOGD("NO RDS data to read..\n");
    return NULL;
    }

    else if( ret > 0)
    {

    V4L2_JBTL_LOGD(" RDS data to read is available..\n");
       for(index=0;index<ret;index+=3)
         rds_decode(buf[index+2] & 0x7,buf[index+1],buf[index]);
    }
  }

  V4L2_JBTL_LOGD("RDS thread exiting..\n");
  return NULL;
}

int fm_read_tuner_capabilities(int radio_fd)
{
  struct v4l2_capability cap;
  int res;

  res = ioctl(radio_fd,VIDIOC_QUERYCAP,&cap);
  if(res < 0)
  {
    V4L2_JBTL_LOGD("Failed to read %s capabilities\n",DEFAULT_RADIO_DEVICE);
    return FM_FAILED;
  }
  if((cap.capabilities & V4L2_CAP_RADIO) == 0)
  {
    V4L2_JBTL_LOGD("%s is not radio devcie",DEFAULT_RADIO_DEVICE);
    return FM_FAILED;
  }
  V4L2_JBTL_LOGD("\n***%s Info ****\n",DEFAULT_RADIO_DEVICE);
  V4L2_JBTL_LOGD("Driver       : %s\n",cap.driver);
  V4L2_JBTL_LOGD("Card         : %s\n",cap.card);
  V4L2_JBTL_LOGD("Bus          : %s\n",cap.bus_info);
  V4L2_JBTL_LOGD("Capabilities : 0x%x\n",cap.capabilities);

  return FM_SUCCESS;
}


static int nativeJFmRx_Create(JNIEnv *env,jobject obj,jobject jContextValue)
{

    int fmStatus ;

   V4L2_JBTL_LOGD("Java_JFmRx_nativeJFmRx_Create(): Entered");

   radio_fd = open(DEFAULT_RADIO_DEVICE, O_RDWR);
   if(radio_fd < 0)
   {
       V4L2_JBTL_LOGD("Unable to open %s ..\n",DEFAULT_RADIO_DEVICE);
      jniThrowIOException(env, errno);
       return FM_FAILED;
   }

   fmStatus = fm_read_tuner_capabilities(radio_fd);
   if(fmStatus< 0)
   {
     close(radio_fd);
     return fmStatus;
   }

    V4L2_JBTL_LOGD("nativeJFmRx_create:Exiting Successfully");

    return fmStatus;
}



static int nativeJFmRx_Destroy(JNIEnv *env, jobject obj,jlong jContextValue)
{

    V4L2_JBTL_LOGD("nativeJFmRx_destroy(): Entered");

    V4L2_JBTL_LOGD("nativeJFmRx_destroy(): Exit");
    return FM_SUCCESS;
}



static int nativeJFmRx_Enable(JNIEnv *env, jobject obj, jlong jContextValue)
{

   int  status ;
   struct v4l2_tuner vtun;

   V4L2_JBTL_LOGD("nativeJFmRx_enable(): Entered");

   jContext = jContextValue;

   vtun.index = 0;
   vtun.audmode = V4L2_TUNER_MODE_STEREO;
   vtun.rxsubchans = V4L2_TUNER_SUB_RDS;

   status = ioctl(radio_fd, VIDIOC_S_TUNER, &vtun);
   if(status < 0)
   {
     V4L2_JBTL_LOGD("Failed to Enable FM\n");
     return status;
   }

   V4L2_JBTL_LOGD("nativeJFmRx_enable: FM_RX_Enable() returned %d",(int)status);
   nativeJFmRx_Callback(jContext,status,FM_RX_CMD_ENABLE,status);
   V4L2_JBTL_LOGD("nativeJFmRx_enable(): Exit");
    return status;
}



static int nativeJFmRx_Disable(JNIEnv *env, jobject obj, jlong jContextValue)
{
    V4L2_JBTL_LOGD("nativeJFmRx_disable(): Entered");

    // Terminate RDS thread
    g_stopCommListener = true;
    isThreadCreated = false;

    close(radio_fd);
    nativeJFmRx_Callback(jContext,0,FM_RX_CMD_DISABLE,0);

    V4L2_JBTL_LOGD("nativeJFmRx_disable(): Exit");;
    return FM_SUCCESS;
}



static int nativeJFmRx_SetBand(JNIEnv *env, jobject obj,jlong jContextValue, jint jFmBand)
{
   int status=0;
   static unsigned char last_band = FM_BAND_EUROPE_US;
   char curr_band;
   int fd, res;

   switch(jFmBand) {
       case 1:
           curr_band = '1';
           break;
       case 0:
       default:
           curr_band = '0';
           break;
   }

   V4L2_JBTL_LOGD("nativeJFmRx_setBand(): EnteredjFmBand  %d",jFmBand);
   V4L2_JBTL_LOGD("nativeJFmRx_setBand(): curr_band %d last_band %d",curr_band,last_band);

   fd = open(FM_BAND_SYSFS_ENTRY, O_RDWR);
   if (fd < 0) {
       V4L2_JBTL_LOGD("Can't open %s", FM_BAND_SYSFS_ENTRY);
       return FM_FAILED;
   }

   res = write(fd, &curr_band, sizeof(char));
   if(res <= 0){
       V4L2_JBTL_LOGD("Failed to set FM Band\n");
       return FM_FAILED;
   }

   nativeJFmRx_Callback(jContext,status,FM_RX_CMD_SET_BAND,status);

   V4L2_JBTL_LOGD("nativeJFmRx_setBand(): Exit");
   return FM_PENDING;
}


static int nativeJFmRx_GetBand(JNIEnv *env, jobject obj,jlong jContextValue)
{

    int status = 0;
    unsigned char curr_band;

nativeJFmRx_Callback(jContext,status,FM_RX_CMD_GET_BAND,curr_band);

    V4L2_JBTL_LOGD("nativeJFmRx_getBand(): Exit");

     return FM_PENDING;
}


static int nativeJFmRx_Tune(JNIEnv *env, jobject obj,jlong jContextValue,jint user_freq)
{
    struct v4l2_frequency vf;
    struct v4l2_tuner vt;
    int status, div;

    V4L2_JBTL_LOGD("nativeJFmRx_tune(): Entered");

    vt.index = 0;
    status = ioctl(radio_fd, VIDIOC_G_TUNER, &vt);
        if(status < 0)
        {
                V4L2_JBTL_LOGD("Failed to get tuner capabilities\n");
                return FM_FAILED;
        }

    vf.tuner = 0;
    vf.frequency = rint(user_freq * 16 + 0.5);

    div = (vt.capability & V4L2_TUNER_CAP_LOW) ? 1000 : 1;
    if (div == 1)
        vf.frequency /=1000;

    status = ioctl(radio_fd, VIDIOC_S_FREQUENCY, &vf);
    if(status < 0)
    {
        V4L2_JBTL_LOGD("Failed to tune to frequency %d\n",user_freq);
        return FM_FAILED;
    }
    V4L2_JBTL_LOGD("Tuned to frequency %2.1f MHz\n",user_freq);

nativeJFmRx_Callback(jContext,status,FM_RX_CMD_TUNE,user_freq);

    V4L2_JBTL_LOGD("nativeJFmRx_Tune(): Exit");
     return FM_PENDING;



}


static int nativeJFmRx_GetTunedFrequency(JNIEnv *env, jobject obj,jlong jContextValue)
{
   struct v4l2_frequency vf;
   int status;
   V4L2_JBTL_LOGD("nativeJFmRx_getTunedFrequency(): Entered");

   status = ioctl(radio_fd, VIDIOC_G_FREQUENCY,&vf);
   if(status < 0)
   {
     V4L2_JBTL_LOGD("Failed to read current frequency\n");
     return FM_FAILED;
   }

   V4L2_JBTL_LOGD("Tuned to frequency %2.1f MHz \n",(float)vf.frequency/1000);
nativeJFmRx_Callback(jContext,status,FM_RX_CMD_GET_TUNED_FREQUENCY,vf.frequency);

    V4L2_JBTL_LOGD("nativeJFmRx_getTunedFrequency(): Exit");
     return FM_PENDING;

}



static int nativeJFmRx_SetMonoStereoMode(JNIEnv *env, jobject obj,jlong jContextValue,jint jFmMode)
{

     struct v4l2_tuner vt;
     int status;
     V4L2_JBTL_LOGD("nativeJFmRx_SetMonoStereoMode(): Entered");

    vt.index = 0;
    vt.audmode = jFmMode;

    status = ioctl(radio_fd, VIDIOC_S_TUNER, &vt);
    if (status < 0){
       V4L2_JBTL_LOGD("Failed to set stereo/mono mode\n");
       return FM_FAILED;
    }

    V4L2_JBTL_LOGD("Set to %d Mode\n",jFmMode);
    nativeJFmRx_Callback(jContext,status, FM_RX_CMD_SET_MONO_STEREO_MODE,status);

    V4L2_JBTL_LOGD("nativeJFmRx_SetMonoStereoMode(): Exit");
    return FM_PENDING;
}



static int nativeJFmRx_GetMonoStereoMode(JNIEnv *env, jobject obj,jlong jContextValue)
{
    struct v4l2_tuner vt;
    int status;
    unsigned char mode;

    V4L2_JBTL_LOGD("nativeJFmRx_GetMonoStereoMode(): Entered");

    vt.index = 0;
    status = ioctl(radio_fd, VIDIOC_G_TUNER, &vt);
    if (status < 0){
       V4L2_JBTL_LOGD("Failed to get stereo/mono mode\n");
       return FM_FAILED;
    }
    mode = vt.audmode;

    V4L2_JBTL_LOGD("%d mode\n",mode);
nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_MONO_STEREO_MODE,mode);

    V4L2_JBTL_LOGD("nativeJFmRx_GetMonoStereoMode(): Exit");
    return FM_PENDING    ;
}



static int nativeJFmRx_SetMuteMode(JNIEnv *env, jobject obj,jlong jContextValue,jint jFmMuteMode)
{

      struct v4l2_control vctrl;
   int status;

    V4L2_JBTL_LOGD("nativeJFmRx_setMuteMode(): Entered");

   vctrl.id = V4L2_CID_AUDIO_MUTE;
   vctrl.value = !jFmMuteMode; /* To Do:: Mapping in future for V4L2*/
   status = ioctl(radio_fd,VIDIOC_S_CTRL,&vctrl);
   if(status < 0)
   {
     V4L2_JBTL_LOGD("Failed to set mute mode\n");
     return FM_FAILED;
   }

nativeJFmRx_Callback(jContext,status, FM_RX_CMD_SET_MUTE_MODE,status);
    V4L2_JBTL_LOGD("nativeJFmRx_setMuteMode(): Exit");
      return FM_PENDING;


}


static int nativeJFmRx_GetMuteMode(JNIEnv *env, jobject obj,jlong jContextValue)
{
    struct v4l2_control vctrl;
    int status;
    V4L2_JBTL_LOGD("nativeJFmRx_getMuteMode(): Entered");
    vctrl.id = V4L2_CID_AUDIO_MUTE;
    status = ioctl(radio_fd,VIDIOC_G_CTRL,&vctrl);
    if(status < 0)
    {
      V4L2_JBTL_LOGD("Failed to get mute mode\n");
      return FM_FAILED;
    }

    V4L2_JBTL_LOGD("%d\n",vctrl.value);
nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_MUTE_MODE,vctrl.value);

    V4L2_JBTL_LOGD("nativeJFmRx_getMuteMode(): Exit");
       return FM_PENDING;
}


static int nativeJFmRx_SetRssiThreshold(JNIEnv *env, jobject obj,jlong jContextValue,jint jFmRssi)
{

    int status;
    char rssi_lvl[10];
    int fd, res;

    V4L2_JBTL_LOGD("nativeJFmRx_setRssiThreshold(): Entered");

    sprintf(rssi_lvl,"%d",jFmRssi);

    V4L2_JBTL_LOGD("nativeJFmRx_setRssiThreshold(): val = %s", rssi_lvl);
    ;
    fd = open(FM_RSSI_LVL_SYSFS_ENTRY, O_RDWR);
    if (fd < 0) {
        V4L2_JBTL_LOGD("Can't open %s", FM_RSSI_LVL_SYSFS_ENTRY);
        return FM_FAILED;
    }

    res = write(fd, &rssi_lvl, sizeof(char));
    if(res <= 0){
        V4L2_JBTL_LOGD("Failed to set FM RSSI level\n");
        return FM_FAILED;
    }

    V4L2_JBTL_LOGD("Setting rssi to %d\n",jFmRssi);

    nativeJFmRx_Callback(jContext,status, FM_RX_CMD_SET_RSSI_THRESHOLD,status);
    V4L2_JBTL_LOGD("nativeJFmRx_setRssiThreshold(): Exit");

    return FM_PENDING;
}

static int nativeJFmRx_GetRssiThreshold(JNIEnv *env, jobject obj,jlong jContextValue)
{

  short rssi_threshold;
   int status;
   V4L2_JBTL_LOGD("nativeJFmRx_getRssiThreshold(): Entered");

   status = 0;

   V4L2_JBTL_LOGD("RSSI threshold set to %d\n",rssi_threshold);
nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_RSSI_THRESHOLD,rssi_threshold);
    V4L2_JBTL_LOGD("nativeJFmRx_getRssiThreshold(): Exit");
     return FM_PENDING;
}

static int nativeJFmRx_GetRssi(JNIEnv *env, jobject obj,jlong jContextValue)
{
    int status;
    short curr_rssi_lvl;

    V4L2_JBTL_LOGD("nativeJFmRx_getRssi(): Entered");

    status = 0;

    V4L2_JBTL_LOGD("RSSI level is %d\n",curr_rssi_lvl);

nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_RSSI,curr_rssi_lvl);
        V4L2_JBTL_LOGD("nativeJFmRx_getRssi(): Exit");
     return FM_PENDING;;

}

static int nativeJFmRx_SetVolume(JNIEnv *env, jobject obj,jlong jContextValue,jint jFmVolume)
{
   struct v4l2_control vctrl;
   int status;

   V4L2_JBTL_LOGD("nativeJFmRx_SetVolume(): Entered");

   vctrl.id = V4L2_CID_AUDIO_VOLUME;
   vctrl.value = jFmVolume;

   status = ioctl(radio_fd,VIDIOC_S_CTRL,&vctrl);
   if(status < 0)
   {
     V4L2_JBTL_LOGD("nativeJFmRx_SetVolume():Failed to set volume\n");
     return status;
   }
   V4L2_JBTL_LOGD("nativeJFmRx_SetVolume():Setting volume to %d \n",jFmVolume);

nativeJFmRx_Callback(jContext,status, FM_RX_CMD_SET_VOLUME,status);

    V4L2_JBTL_LOGD("nativeJFmRx_SetVolume(): Exit");
     return FM_PENDING;


}

static int nativeJFmRx_GetVolume(JNIEnv *env, jobject obj,jlong jContextValue)
{
    struct v4l2_control vctrl;
    int status;

    V4L2_JBTL_LOGD("nativeJFmRx_getVolume(): Entered");


   vctrl.id = V4L2_CID_AUDIO_VOLUME;
   status = ioctl(radio_fd,VIDIOC_G_CTRL,&vctrl);
   if(status < 0)
   {
     V4L2_JBTL_LOGD("Failed to get volume\n");
     return status;
   }

nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_VOLUME,vctrl.value);
    V4L2_JBTL_LOGD("nativeJFmRx_getVolume(): Exit");
       return FM_PENDING;
}

static int nativeJFmRx_SetChannelSpacing(JNIEnv *env, jobject obj,jlong jContextValue,jint jFmChannelSpacing)
{

    int status = 0;
    ALOGD("nativeJFmRx_SetChannelSpacing(): Entered");

    chanl_spacing = jFmChannelSpacing * 50000;

    nativeJFmRx_Callback(jContext,status, FM_RX_CMD_SET_CHANNEL_SPACING,status);

    ALOGD("nativeJFmRx_SetChannelSpacing(): Exit");
    return FM_PENDING;

}

static int nativeJFmRx_GetChannelSpacing(JNIEnv *env, jobject obj,jlong jContextValue)
{

    int status =0;
    ALOGD("nativeJFmRx_GetChannelSpacing(): Entered");

      ALOGD("nativeJFmRx_GetChannelSpacing(): Exit");
    nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_CHANNEL_SPACING,status);
     return FM_PENDING;
}

static jint nativeJFmRx_SetDeEmphasisFilter(JNIEnv *env, jobject obj,jlong jContextValue,jint jFmEmphasisFilter)
{

   int status;
    V4L2_JBTL_LOGD("nativeJFmRx_SetDeEmphasisFilter(): Entered");

    V4L2_JBTL_LOGD("1. nativeJFmRx_EnableRDS\n");
    status = 0;

   V4L2_JBTL_LOGD("Set to De-emphasis %d mode\n",jFmEmphasisFilter);
nativeJFmRx_Callback(jContext,status, FM_RX_CMD_SET_DEEMPHASIS_FILTER,status);
    V4L2_JBTL_LOGD("nativeJFmRx_SetDeEmphasisFilter(): Exit");
    V4L2_JBTL_LOGD("2. nativeJFmRx_EnableRDS\n");
     return FM_PENDING;
}


static int nativeJFmRx_GetDeEmphasisFilter(JNIEnv *env, jobject obj,jlong jContextValue)
{

    int status;
    unsigned char mode;

    V4L2_JBTL_LOGD("nativeJFmRx_GetDeEmphasisFilter(): Entered");

    V4L2_JBTL_LOGD("1. nativeJFmRx_EnableRDS\n");
    mode = 0;

    V4L2_JBTL_LOGD("De-emphasis filter %d\n",mode);
nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_DEEMPHASIS_FILTER,mode);

    V4L2_JBTL_LOGD("nativeJFmRx_GetDeEmphasisFilter(): Exit");
    V4L2_JBTL_LOGD("2. nativeJFmRx_EnableRDS\n");
     return FM_PENDING;
}



static int nativeJFmRx_Seek(JNIEnv *env, jobject obj,jlong jContextValue,jint jdirection)
{

     struct ti_v4l2_hw_freq_seek frq_seek;
    struct v4l2_frequency vf;
        struct v4l2_tuner vt;
    int status, div;

    V4L2_JBTL_LOGD("nativeJFmRx_Seek(): Entered");
    V4L2_JBTL_LOGD("Seeking %s.. and channel spacing is %d\n",jdirection?"up":"down", chanl_spacing);
    frq_seek.seek_upward = jdirection;
        frq_seek.type = (v4l2_tuner_type)1;
        frq_seek.spacing = chanl_spacing;
        frq_seek.wrap_around = 0;

    errno = 0;
    status = ioctl(radio_fd,VIDIOC_S_HW_FREQ_SEEK,&frq_seek);
    if(errno == EAGAIN)
    {
      V4L2_JBTL_LOGD("Band limit reached\n");
    }
    else if(status <0)
    {
      V4L2_JBTL_LOGD("Seek operation failed\n");
      return status;
    }

    V4L2_JBTL_LOGD("nativeJFmRx_tune(): Entered");

        vt.index = 0;
        status = ioctl(radio_fd, VIDIOC_G_TUNER, &vt);
        if(status < 0)
        {
                V4L2_JBTL_LOGD("Failed to get tuner capabilities\n");
                return FM_FAILED;
        }

        div = (vt.capability & V4L2_TUNER_CAP_LOW) ? 1000 : 1;

     status = ioctl(radio_fd, VIDIOC_G_FREQUENCY,&vf);
     if(status < 0)
     {
       V4L2_JBTL_LOGD("Failed to read current frequency\n");
       return status;
     }

     V4L2_JBTL_LOGD("Tuned to frequency %3.2f MHz \n",vf.frequency / (16.0 * div));

    nativeJFmRx_Callback(jContext,status, FM_RX_CMD_SEEK,vf.frequency * 1000 / (16 * div));

        V4L2_JBTL_LOGD("nativeJFmRx_Seek(): Exit");
         return FM_PENDING;

}


static int nativeJFmRx_StopSeek(JNIEnv *env, jobject obj,jlong jContextValue)
{
int status =0;
    V4L2_JBTL_LOGD("nativeJFmRx_StopSeek(): Entered");
 nativeJFmRx_Callback(jContext,status, FM_RX_CMD_STOP_SEEK,status);
    V4L2_JBTL_LOGD("nativeJFmRx_StopSeek(): Exit");
         return FM_PENDING;
}

static int nativeJFmRx_EnableRDS(JNIEnv *env, jobject obj,jlong jContextValue)
{

    int status;
    unsigned char rds_mode = FM_RDS_ENABLE;
    struct v4l2_tuner vt;

    V4L2_JBTL_LOGD("nativeJFmRx_enableRDS(): Entered");

    V4L2_JBTL_LOGD("1. nativeJFmRx_EnableRDS\n");
    vt.index = 0;
    status = ioctl(radio_fd, VIDIOC_G_TUNER, &vt);
    if(status < 0)
    {
        V4L2_JBTL_LOGD("Failed to get tuner attributes\n");
        return status;
    }

    V4L2_JBTL_LOGD("2. nativeJFmRx_EnableRDS\n");

        if ((vt.rxsubchans & V4L2_TUNER_SUB_RDS) != 1)
                vt.rxsubchans |= V4L2_TUNER_SUB_RDS;

    status = ioctl(radio_fd, VIDIOC_S_TUNER, &vt);
    if(status < 0)
    {
        V4L2_JBTL_LOGD("Failed to set RDS on/off status\n");
        return status;
    }

    V4L2_JBTL_LOGD("3. nativeJFmRx_EnableRDS\n");
    if(isThreadCreated == false)
    {

        V4L2_JBTL_LOGD(" nativeJFmRx_EnableRDS: creating thread !!! \n");
        g_stopCommListener = false;
        /* Create rds receive thread once */
        status = pthread_create(&p_threadHandle,   /* Thread Handle. */
                    NULL,                               /* Default Atributes. */
                    entryFunctionForRdsThread,            /* Entry Function. */
                    (void *)radio_fd);           /* Parameters. */
        if (status < 0)
        {
            V4L2_JBTL_LOGD(" nativeJFmRx_EnableRDS: Thread Creation FAILED !!! \n");
            return FM_ERR_THREAD_CREATION_FAILED;
        }

        isThreadCreated = true;
    }
    else
        V4L2_JBTL_LOGD("RDS thread already created\n");

    V4L2_JBTL_LOGD("4. nativeJFmRx_EnableRDS\n");
    V4L2_JBTL_LOGD("RDS %d\n",rds_mode);

    nativeJFmRx_Callback(jContext,status, FM_RX_CMD_ENABLE_RDS,status);
    V4L2_JBTL_LOGD("nativeJFmRx_enableRDS(): Exit");
    return FM_PENDING;
}

static int nativeJFmRx_DisableRDS(JNIEnv *env, jobject obj,jlong jContextValue)
{

    int status;
    unsigned char rds_mode = FM_RDS_DISABLE;
    struct v4l2_tuner vt;

        V4L2_JBTL_LOGD("1. nativeJFmRx_DisableRDS\n");
        vt.index = 0;
        status = ioctl(radio_fd, VIDIOC_G_TUNER, &vt);
        if(status < 0)
        {
                V4L2_JBTL_LOGD("Failed to get tuner attributes\n");
                return status;
        }

    if(vt.rxsubchans & V4L2_TUNER_SUB_RDS)
        vt.rxsubchans &= ~V4L2_TUNER_SUB_RDS;

        V4L2_JBTL_LOGD("2. nativeJFmRx_DisableRDS and vt.rxsubchans = %d\n", vt.rxsubchans);

        status = ioctl(radio_fd, VIDIOC_S_TUNER, &vt);
        if(status < 0)
        {
                V4L2_JBTL_LOGD("Failed to set RDS on/off status\n");
                return status;
        }

nativeJFmRx_Callback(jContext,status, FM_RX_CMD_DISABLE_RDS,status);

    V4L2_JBTL_LOGD("nativeJFmRx_DisableRDS(): Exit");
     return FM_PENDING;
}

static int nativeJFmRx_EnableAudioRouting(JNIEnv *env, jobject obj,jlong jContextValue)
{
   int status = 0 ;
    V4L2_JBTL_LOGD("nativeJFmRx_enableAudioRouting(): Entered");

   nativeJFmRx_Callback(jContext,status, FM_RX_CMD_ENABLE_AUDIO,status);

    V4L2_JBTL_LOGD("nativeJFmRx_enableAudioRouting(): Exit");
     return FM_PENDING;
}

static int  nativeJFmRx_DisableAudioRouting(JNIEnv *env, jobject obj,jlong jContextValue)
{
   int status = 0 ;
    V4L2_JBTL_LOGD("nativeJFmRx_disableAudioRouting(): Entered");

   nativeJFmRx_Callback(jContext,status, FM_RX_CMD_ENABLE_AUDIO,status);

    V4L2_JBTL_LOGD("nativeJFmRx_disableAudioRouting(): Exit");
     return FM_PENDING;
}

static int nativeJFmRx_SetRdsAfSwitchMode(JNIEnv *env, jobject obj,jlong jContextValue,jint jRdsAfSwitchMode)
{

    int status;
    char af_switch;
    int fd, res;

    V4L2_JBTL_LOGD("nativeJFmRx_setRdsAfSwitchMode(): Entered");

    switch(jRdsAfSwitchMode) {
        case 1:
            af_switch = '1';
            break;
        case 0:
        default:
            af_switch = '0';
            break;
    }

    fd = open(FM_RDS_AF_SYSFS_ENTRY, O_RDWR);
    if (fd < 0) {
        V4L2_JBTL_LOGD("Can't open %s", FM_RDS_AF_SYSFS_ENTRY);
        return FM_FAILED;
    }

    res = write(fd, &af_switch, sizeof(char));
    if(res <= 0){
        V4L2_JBTL_LOGD("Failed to set FM AF Switch\n");
        return FM_FAILED;
    }


    V4L2_JBTL_LOGD("AF Switch %d ",jRdsAfSwitchMode);

    nativeJFmRx_Callback(jContext,status, FM_RX_CMD_SET_RDS_AF_SWITCH_MODE,status);
    V4L2_JBTL_LOGD("nativeJFmRx_setRdsAfSwitchMode(): Exit");
    return FM_PENDING;

}

static int nativeJFmRx_GetRdsAfSwitchMode(JNIEnv *env, jobject obj,jlong jContextValue)
{

    int status;
     unsigned char af_mode;


    V4L2_JBTL_LOGD("nativeJFmRx_getRdsAfSwitchMode(): Entered");

    status = 0;

nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_RDS_AF_SWITCH_MODE,af_mode);
    V4L2_JBTL_LOGD("nativeJFmRx_getRdsAfSwitchMode(): Exit");
     return FM_PENDING;
}

static int   nativeJFmRx_ChangeAudioTarget (JNIEnv *env, jobject obj,jlong jContextValue, jint jFmRxAudioTargetMask, jint digitalConfig)
{

    V4L2_JBTL_LOGD("nativeJFmRx_ChangeAudioTarget(): Entered");
//nativeJFmRx_Callback(jContext,status, FM_RX_CMD_CHANGE_AUDIO_TARGET,status);
      V4L2_JBTL_LOGD("nativeJFmRx_ChangeAudioTarget(): Exit");
         return FM_PENDING;

}


static int    nativeJFmRx_ChangeDigitalTargetConfiguration(JNIEnv *env, jobject obj,jlong jContextValue,jint digitalConfig)
{

    V4L2_JBTL_LOGD("nativeJFmRx_ChangeDigitalTargetConfiguration(): Entered");

 //nativeJFmRx_Callback(jContext,status, FM_RX_CMD_CHANGE_DIGITAL_AUDIO_CONFIGURATION,status);

    V4L2_JBTL_LOGD("nativeJFmRx_ChangeDigitalTargetConfiguration(): Exit");
     return FM_PENDING;

}


static int   nativeJFmRx_SetRfDependentMuteMode(JNIEnv *env, jobject obj,jlong jContextValue, jint rf_mute)
{

      int status;
        V4L2_JBTL_LOGD("nativeJFmRx_SetRfDependentMuteMode(): Entered");

    status = 0;

nativeJFmRx_Callback(jContext,status, FM_RX_CMD_SET_RF_DEPENDENT_MUTE_MODE,status);
    V4L2_JBTL_LOGD("nativeJFmRx_SetRfDependentMuteMode(): Exit");
     return FM_PENDING;



}


static int    nativeJFmRx_GetRfDependentMute(JNIEnv *env, jobject obj,jlong jContextValue)
{

    int status;
     unsigned char rf_mute;
    V4L2_JBTL_LOGD(" nativeJFmRx_GetRfDependentMute(): Entered");

    status = 0;

nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_RF_DEPENDENT_MUTE_MODE,rf_mute);
    V4L2_JBTL_LOGD(" nativeJFmRx_GetRfDependentMute(): Exit");
     return FM_PENDING;

}


static int    nativeJFmRx_SetRdsSystem(JNIEnv *env, jobject obj,jlong jContextValue, jint rdsSystem)
{
    int status;

     V4L2_JBTL_LOGD(" nativeJFmRx_SetRdsSystem(): Entered");

    V4L2_JBTL_LOGD("entered to ELSE\n");
    status = 0;

    V4L2_JBTL_LOGD("Set to %d\n",rdsSystem);
    nativeJFmRx_Callback(jContext,status,FM_RX_CMD_SET_RDS_SYSTEM,status);
    V4L2_JBTL_LOGD(" nativeJFmRx_SetRdsSystem(): Exit");
     return FM_PENDING;



}


static  int   nativeJFmRx_GetRdsSystem(JNIEnv *env, jobject obj,jlong jContextValue)
{

    int status;
     unsigned char mode;

    V4L2_JBTL_LOGD("nativeJFmRx_GetRdsSystem(): Entered");

    status = 0;

nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_RDS_SYSTEM,mode);
    V4L2_JBTL_LOGD(" nativeJFmRx_GetRdsSystem(): Exit");
     return FM_PENDING;

}


static int   nativeJFmRx_SetRdsGroupMask(JNIEnv *env, jobject obj,jlong jContextValue, jlong groupMask)
{
int status =0;
    V4L2_JBTL_LOGD("nativeJFmRx_SetRdsGroupMask(): Entered");


nativeJFmRx_Callback(jContext,status, FM_RX_CMD_SET_RDS_GROUP_MASK,status);
    V4L2_JBTL_LOGD(" nativeJFmRx_SetRdsGroupMask(): Exit");
     return FM_PENDING;

}

static int   nativeJFmRx_GetRdsGroupMask(JNIEnv *env, jobject obj,jlong jContextValue)
{
int status =0;
    V4L2_JBTL_LOGD("nativeJFmRx_GetRdsGroupMask(): Entered");


nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_RDS_GROUP_MASK,status);
    V4L2_JBTL_LOGD(" nativeJFmRx_GetRdsGroupMask(): Exit");
     return FM_PENDING;

}

static int nativeJFmRx_CompleteScan(JNIEnv *env, jobject obj, jlong jContextValue)
{

int status =0;
    ALOGD("nativeJFmRx_CompleteScan(): Entered");

    //nativeJFmRx_Callback(jContext,status, FM_RX_CMD_COMPLETE_SCAN,status);
    ALOGD("nativeJFmRx_CompleteScan(): Exit");
     return FM_PENDING;
}

static int nativeJFmRx_GetCompleteScanProgress(JNIEnv *env, jobject obj, jlong jContextValue)
{
int status =0;
    ALOGD("nativeJFmRx_GetCompleteScanProgress(): Entered");
  //nativeJFmRx_Callback(jContext,status, FM_RX_CMD_COMPLETE_SCAN_PROGRESS,status);

    ALOGD("nativeJFmRx_GetCompleteScanProgress(): Exit");
     return FM_PENDING;
}

static int nativeJFmRx_StopCompleteScan(JNIEnv *env, jobject obj, jlong jContextValue)
{

    ALOGD("nativeJFmRx_StopCompleteScan(): Entered");

 //nativeJFmRx_Callback(jContext,status, FM_RX_CMD_STOP_COMPLETE_SCAN,status);
    ALOGD("nativeJFmRx_StopCompleteScan(): Exit");
     return FM_PENDING;
}

static int nativeJFmRx_IsValidChannel(JNIEnv *env, jobject obj, jlong jContextValue)
{


    ALOGD("nativeJFmRx_IsValidChannel(): Entered");
//nativeJFmRx_Callback(jContext,status, FM_RX_CMD_IS_CHANNEL_VALID ,status);
    ALOGD("nativeJFmRx_IsValidChannel(): Exit");
     return FM_PENDING;
}


static int nativeJFmRx_GetFwVersion(JNIEnv *env, jobject obj, jlong jContextValue)
{

    ALOGD("nativeJFmRx_GetFwVersion(): Entered");
//nativeJFmRx_Callback(jContext,status, FM_RX_CMD_GET_FW_VERSION,status);
    ALOGD("nativeJFmRx_GetFwVersion(): Exit");
     return FM_PENDING;
}


//################################################################################

//                                 SIGNALS

//###############################################################################

extern "C"
{

void nativeJFmRx_RadioText_Callback(int status, bool resetDisplay,
            unsigned char * msg, int len, int startIndex,
            int repertoire)
{
    ALOGE("nativeJFmRx_RadioText_Callback: Entering");

ALOGE("nativeJFmRx_RadioText_Callback: msg %s",msg);
    JNIEnv* env = NULL;
        bool attachedThread = false;
    int jRet ;
    jbyteArray jRadioTxtMsg = NULL;

 /* check whether the current thread is attached to a virtual machine instance,
   if no only then try to attach to the current thread. */
        jRet = g_jVM->GetEnv((void **)&env,JNI_VERSION_1_4);

       if(jRet < 0)
       {
           ALOGE("failed to get JNI env,assuming native thread");
           jRet = g_jVM->AttachCurrentThread((&env), NULL);

           if(jRet != JNI_OK)
           {
               ALOGE("failed to atatch to current thread %d",jRet);
               return ;
           }

           attachedThread = true;
       }




       if(env == NULL) {
               ALOGI("%s: Entered, env is null", __func__);
           } else {
               ALOGD("%s: jEnv %p", __func__, (void *)env);
           }


V4L2_JBTL_LOGD("nativeJFmRx_Callback():EVENT --------------->FM_RX_EVENT_RADIO_TEXT");
        jRadioTxtMsg = env->NewByteArray(len);
        if (jRadioTxtMsg == NULL) {
            ALOGE("%s: Failed converting elements", __func__);
            goto CLEANUP;
        }

        env->SetByteArrayRegion(jRadioTxtMsg,
                0,
                len,
                (jbyte*)msg);

        if (env->ExceptionOccurred()) {
            ALOGE("%s: Calling nativeCb_fmRxRadioText failed",
                 __func__);
            goto CLEANUP;
        }

        env->CallStaticVoidMethod(_sJClass,
                _sMethodId_nativeCb_fmRxRadioText,(jlong)jContext,
                (jint)status,
                (jboolean)resetDisplay,
                jRadioTxtMsg,
                (jint)len,
                (jint)startIndex,
                (jint)repertoire);

    if (env->ExceptionOccurred()) {
            ALOGE("nativeJFmRx_RadioText_Callback:  ExceptionOccurred");
            goto CLEANUP;
        }

if(jRadioTxtMsg!= NULL)
        env->DeleteLocalRef(jRadioTxtMsg);

        if(attachedThread == true)
              g_jVM->DetachCurrentThread();

return ;

    CLEANUP:
ALOGE("nativeJFmRx_RadioText_Callback: Exiting due to failure");

if(jRadioTxtMsg!= NULL)
        env->DeleteLocalRef(jRadioTxtMsg);
    if (env->ExceptionOccurred())    {
    env->ExceptionDescribe();
    env->ExceptionClear();
    }

        if(attachedThread == true)
      g_jVM->DetachCurrentThread();
return ;
}





   void nativeJFmRx_PS_Callback(long context,int status, int freq,
               int len,unsigned char * name,
               int repertoire)

   {
       ALOGE("nativeJFmRx_PS_Callback: Exiting due to failure");
       JNIEnv* env = NULL;
           bool attachedThread = false;
       int jRet ;
       jbyteArray jNameString = NULL;
 int frequency =0;

   /* check whether the current thread is attached to a virtual machine instance,
   if no only then try to attach to the current thread. */
        jRet = g_jVM->GetEnv((void **)&env,JNI_VERSION_1_4);

       if(jRet < 0)
       {
           ALOGE("failed to get JNI env,assuming native thread");
           jRet = g_jVM->AttachCurrentThread((&env), NULL);

           if(jRet != JNI_OK)
           {
               ALOGE("failed to atatch to current thread %d",jRet);
               return ;
           }

           attachedThread = true;
       }




       if(env == NULL) {
               ALOGI("%s: Entered, env is null", __func__);
           } else {
               ALOGD("%s: jEnv %p", __func__, (void *)env);
           }

              V4L2_JBTL_LOGD("nativeJFmRx_PS_Callback():EVENT --------------->FM_RX_EVENT_PS_CHANGED len %d",len);


             jNameString = env->NewByteArray(len);

             if (jNameString == NULL)
             {
                 V4L2_JBTL_LOGD("nativeJFmRx_PS_Callback: Failed converting elements");
                 goto CLEANUP;
             }

             env->SetByteArrayRegion(jNameString,0,len,(jbyte*)name);

             if (env->ExceptionOccurred())      {
                 V4L2_JBTL_LOGD("nativeJFmRx_PS_Callback: Calling Java nativeCb_fmRxRadioText failed");
                 goto CLEANUP;
             }

             env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxPsChanged,(jlong)context,
                                       (jint)status,
                                       (jint)frequency,
                                       jNameString,
                                       (jint)repertoire);


       if (env->ExceptionOccurred()) {
               ALOGE("nativeJFmRx_PS_Callback:    ExceptionOccurred");
               goto CLEANUP;
           }

   if(jNameString!= NULL)
           env->DeleteLocalRef(jNameString);

           if(attachedThread == true)
                 g_jVM->DetachCurrentThread();

   return ;

       CLEANUP:
   ALOGE("nativeJFmRx_PS_Callback: Exiting due to failure");

   if(jNameString!= NULL)
           env->DeleteLocalRef(jNameString);
       if (env->ExceptionOccurred())    {
       env->ExceptionDescribe();
       env->ExceptionClear();
       }

           if(attachedThread == true)
         g_jVM->DetachCurrentThread();
   return ;
   }


    void nativeJFmRx_Callback(long context, int status,
            int command, long value)
    {

        V4L2_JBTL_LOGI("nativeJFmRx_Callback: Entered, ");

    JNIEnv* env = NULL;
    bool attachedThread = false;
    int jRet ;

/* check whether the current thread is attached to a virtual machine instance,
if no only then try to attach to the current thread. */

    jRet = g_jVM->GetEnv((void **)&env,JNI_VERSION_1_4);

    if(jRet < 0)
    {
         V4L2_JBTL_LOGI("failed to get JNI env,assuming native thread");
        jRet = g_jVM->AttachCurrentThread((&env), NULL);

        if(jRet != JNI_OK)
        {
             V4L2_JBTL_LOGI("failed to atatch to current thread %d",jRet);
            return ;
        }

        attachedThread = true;
    }

    if(env == NULL)
    {
         V4L2_JBTL_LOGD("nativeJFmRx_Callback: Entered, env is null");
    }


           switch (command)
    {

            case FM_RX_CMD_ENABLE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdEnable,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_DISABLE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdDisable,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_BAND:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetBand,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_BAND:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetBand,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_MONO_STEREO_MODE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetMonoStereoMode,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_MONO_STEREO_MODE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetMonoStereoMode,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_MUTE_MODE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetMuteMode,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_MUTE_MODE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetMuteMode,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_RF_DEPENDENT_MUTE_MODE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetRfDependentMuteMode,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_RF_DEPENDENT_MUTE_MODE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetRfDependentMuteMode,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_RSSI_THRESHOLD:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetRssiThreshhold,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_RSSI_THRESHOLD:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetRssiThreshhold,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_DEEMPHASIS_FILTER:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetDeemphasisFilter,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_DEEMPHASIS_FILTER:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetDeemphasisFilter,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_VOLUME:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetVolume,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_VOLUME:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetVolume,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_TUNE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdTune,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_TUNED_FREQUENCY:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetTunedFrequency,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SEEK:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSeek,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_STOP_SEEK:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdStopSeek,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_RSSI:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetRssi,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_ENABLE_RDS:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdEnableRds,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_DISABLE_RDS:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdDisableRds,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_RDS_SYSTEM:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetRdsSystem,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_RDS_SYSTEM:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetRdsSystem,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_RDS_GROUP_MASK:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetRdsGroupMask,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_RDS_GROUP_MASK:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetRdsGroupMask,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_RDS_AF_SWITCH_MODE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetRdsAfSwitchMode,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_RDS_AF_SWITCH_MODE:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetRdsAfSwitchMode,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_ENABLE_AUDIO:
        V4L2_JBTL_LOGD("nativeJFmRx_Callback: at FM_RX_CMD_ENABLE_AUDIO step 1");
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdEnableAudio,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
        V4L2_JBTL_LOGD("nativeJFmRx_Callback: at FM_RX_CMD_ENABLE_AUDIO step 2");
                break;

            case FM_RX_CMD_DISABLE_AUDIO:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdDisableAudio, (jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_CHANGE_AUDIO_TARGET:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdChangeAudioTarget,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_CHANGE_DIGITAL_AUDIO_CONFIGURATION:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdChangeDigitalAudioConfiguration,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_SET_CHANNEL_SPACING:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdSetChannelSpacing,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_CHANNEL_SPACING:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetChannelSpacing,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_GET_FW_VERSION:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetFwVersion,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_IS_CHANNEL_VALID:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdIsValidChannel,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_COMPLETE_SCAN_PROGRESS:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdGetCompleteScanProgress,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            case FM_RX_CMD_STOP_COMPLETE_SCAN:
                env->CallStaticVoidMethod(_sJClass,_sMethodId_nativeCb_fmRxCmdStopCompleteScan,(jlong)context,
                                          (jint)status,
                                          (jint)command,
                                          (jlong)value);
                break;

            default:
                V4L2_JBTL_LOGD("nativeJFmRx_Callback:FM_RX_EVENT_CMD_DONE,unhendeld event");
                break;
            }

        if (env->ExceptionOccurred())    {
            V4L2_JBTL_LOGD("nativeJFmRx_Callback:  ExceptionOccurred");
            goto EXCEPTION;
        }

        V4L2_JBTL_LOGD("nativeJFmRx_Callback: Exiting, Calling DetachCurrentThread at the END");
     if(attachedThread == true)
        g_jVM->DetachCurrentThread();

        return;

EXCEPTION:

        /*Delete Jni Local refrencece */
        V4L2_JBTL_LOGD("nativeJFmRx_Callback: Exiting due to failure");
        if (env->ExceptionOccurred())    {
            env->ExceptionDescribe();
            env->ExceptionClear();
        }
 if(attachedThread == true)
        g_jVM->DetachCurrentThread();

        return;

    }


} //extern c


/**********************************************************************
*                Callback registration

***********************************************************************/
#define VERIFY_METHOD_ID(methodId) \
        if (!_VerifyMethodId(methodId, #methodId)) { \
            V4L2_JBTL_LOGD("Error obtaining method id for %s", #methodId);    \
            return;     \
        }

static bool _VerifyMethodId(jmethodID methodId, const char *name)
{
    bool result = true;

    if (methodId == NULL)
    {
        V4L2_JBTL_LOGD("_VerifyMethodId: Failed getting method id of %s", name);
        result = false;
    }

    return result;
}



void nativeJFmRx_ClassInitNative(JNIEnv* env, jclass clazz){
    V4L2_JBTL_LOGD("nativeJFmRx_ClassInitNative: Entered");

    if (NULL == env)
    {
        V4L2_JBTL_LOGD("nativeJFmRx_ClassInitNative: NULL == env");
    }

    env->GetJavaVM(&g_jVM);



    /* Save class information in global reference in order to prevent class unloading */
    _sJClass = (jclass)env->NewGlobalRef(clazz);


    V4L2_JBTL_LOGI("nativeJFmRx_ClassInitNative: Obtaining method IDs");

    _sMethodId_nativeCb_fmRxRadioText  = env->GetStaticMethodID(clazz,
                                         "nativeCb_fmRxRadioText",
                                         "(JIZ[BIII)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxRadioText);


    _sMethodId_nativeCb_fmRxPsChanged  = env->GetStaticMethodID(clazz,
                                         "nativeCb_fmRxPsChanged",
                                         "(JII[BI)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxPsChanged);

    /* Complete parsing of the RDS data has not been implemented yet
    Commented the FM RX RDS callbacks functionality start*/

    #if 0
    _sMethodId_nativeCb_fmRxRawRDS = env->GetStaticMethodID(clazz,
                                     "nativeCb_fmRxRawRDS",
                                     "(JII[B)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxRawRDS);


    _sMethodId_nativeCb_fmRxPiCodeChanged  = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxPiCodeChanged",
            "(JII)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxPiCodeChanged);


    _sMethodId_nativeCb_fmRxPtyCodeChanged  = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxPtyCodeChanged",
            "(JII)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxPtyCodeChanged);




    _sMethodId_nativeCb_fmRxMonoStereoModeChanged  = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxMonoStereoModeChanged",
            "(JII)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxMonoStereoModeChanged);


    _sMethodId_nativeCb_fmRxAudioPathChanged  = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxAudioPathChanged",
            "(JI)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxAudioPathChanged);


    _sMethodId_nativeCb_fmRxAfSwitchFreqFailed  = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxAfSwitchFreqFailed",
            "(JIIII)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxAfSwitchFreqFailed);


    _sMethodId_nativeCb_fmRxAfSwitchStart  = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxAfSwitchStart",
            "(JIIII)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxAfSwitchStart);


    _sMethodId_nativeCb_fmRxAfSwitchComplete  = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxAfSwitchComplete",
            "(JIIII)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxAfSwitchComplete);


    _sMethodId_nativeCb_fmRxAfListChanged  = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxAfListChanged",
            "(JII[BI)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxAfListChanged);

#endif
    /*Commented the FM RX RDS callbacks functionality end*/


    _sMethodId_nativeCb_fmRxCmdEnable = env->GetStaticMethodID(clazz,
                                        "nativeCb_fmRxCmdEnable",
                                        "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdEnable);


    _sMethodId_nativeCb_fmRxCmdDisable = env->GetStaticMethodID(clazz,
                                         "nativeCb_fmRxCmdDisable",
                                         "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdDisable);

    _sMethodId_nativeCb_fmRxCmdEnableAudio = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdEnableAudio",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdEnableAudio);



    _sMethodId_nativeCb_fmRxCmdChangeAudioTarget = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdChangeAudioTarget",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdChangeAudioTarget);


    _sMethodId_nativeCb_fmRxCmdSetBand = env->GetStaticMethodID(clazz,
                                         "nativeCb_fmRxCmdSetBand",
                                         "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetBand);

    _sMethodId_nativeCb_fmRxCmdGetBand = env->GetStaticMethodID(clazz,
                                         "nativeCb_fmRxCmdGetBand",
                                         "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetBand);



    _sMethodId_nativeCb_fmRxCmdSetMonoStereoMode = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdSetMonoStereoMode",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetMonoStereoMode);



    _sMethodId_nativeCb_fmRxCmdGetMonoStereoMode = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetMonoStereoMode",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetMonoStereoMode);



    _sMethodId_nativeCb_fmRxCmdGetMuteMode = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetMuteMode",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetMuteMode);



    _sMethodId_nativeCb_fmRxCmdSetMuteMode = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdSetMuteMode",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetMuteMode);



    _sMethodId_nativeCb_fmRxCmdSetRfDependentMuteMode = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdSetRfDependentMuteMode",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetRfDependentMuteMode);



    _sMethodId_nativeCb_fmRxCmdGetRfDependentMuteMode = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetRfDependentMuteMode",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetRfDependentMuteMode);



    _sMethodId_nativeCb_fmRxCmdSetRssiThreshhold = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdSetRssiThreshhold",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetRssiThreshhold);



    _sMethodId_nativeCb_fmRxCmdGetRssiThreshhold = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetRssiThreshhold",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetRssiThreshhold);



    _sMethodId_nativeCb_fmRxCmdSetDeemphasisFilter = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdSetDeemphasisFilter",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetDeemphasisFilter);


    _sMethodId_nativeCb_fmRxCmdGetDeemphasisFilter = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetDeemphasisFilter",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetDeemphasisFilter);



    _sMethodId_nativeCb_fmRxCmdSetVolume = env->GetStaticMethodID(clazz,
                                           "nativeCb_fmRxCmdSetVolume",
                                           "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetVolume);



    _sMethodId_nativeCb_fmRxCmdGetVolume = env->GetStaticMethodID(clazz,
                                           "nativeCb_fmRxCmdGetVolume",
                                           "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetVolume);

    _sMethodId_nativeCb_fmRxCmdSetChannelSpacing = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdSetChannelSpacing",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetChannelSpacing);



    _sMethodId_nativeCb_fmRxCmdGetChannelSpacing = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetChannelSpacing",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetChannelSpacing);



    _sMethodId_nativeCb_fmRxCmdTune = env->GetStaticMethodID(clazz,
                                      "nativeCb_fmRxCmdTune",
                                      "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdTune);


    _sMethodId_nativeCb_fmRxCmdGetTunedFrequency = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetTunedFrequency",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetTunedFrequency);


    _sMethodId_nativeCb_fmRxCmdSeek = env->GetStaticMethodID(clazz,
                                      "nativeCb_fmRxCmdSeek",
                                      "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSeek);



    _sMethodId_nativeCb_fmRxCmdStopSeek = env->GetStaticMethodID(clazz,
                                          "nativeCb_fmRxCmdStopSeek",
                                          "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdStopSeek);


    _sMethodId_nativeCb_fmRxCmdGetRssi = env->GetStaticMethodID(clazz,
                                         "nativeCb_fmRxCmdGetRssi",
                                         "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetRssi);


    _sMethodId_nativeCb_fmRxCmdEnableRds = env->GetStaticMethodID(clazz,
                                           "nativeCb_fmRxCmdEnableRds",
                                           "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdEnableRds);


    _sMethodId_nativeCb_fmRxCmdDisableRds = env->GetStaticMethodID(clazz,
                                            "nativeCb_fmRxCmdDisableRds",
                                            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdDisableRds);


    _sMethodId_nativeCb_fmRxCmdGetRdsSystem = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetRdsSystem",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetRdsSystem);



    _sMethodId_nativeCb_fmRxCmdSetRdsSystem = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdSetRdsSystem",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetRdsSystem);


    _sMethodId_nativeCb_fmRxCmdSetRdsGroupMask = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdSetRdsGroupMask",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetRdsGroupMask);


    _sMethodId_nativeCb_fmRxCmdGetRdsGroupMask = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetRdsGroupMask",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetRdsGroupMask);


    _sMethodId_nativeCb_fmRxCmdSetRdsAfSwitchMode = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdSetRdsAfSwitchMode",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdSetRdsAfSwitchMode);


    _sMethodId_nativeCb_fmRxCmdGetRdsAfSwitchMode = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetRdsAfSwitchMode",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetRdsAfSwitchMode);


    _sMethodId_nativeCb_fmRxCmdDisableAudio = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdDisableAudio",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdDisableAudio);

    _sMethodId_nativeCb_fmRxCmdDestroy = env->GetStaticMethodID(clazz,
                                         "nativeCb_fmRxCmdDestroy",
                                         "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdDestroy);


    _sMethodId_nativeCb_fmRxCmdChangeDigitalAudioConfiguration= env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdChangeDigitalAudioConfiguration",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdChangeDigitalAudioConfiguration);

    /* Complete scan in V4l2 FM driver is not implemented yet
    Commented the FM RX Completescan functionality start*/

    /*_sMethodId_nativeCb_fmRxCompleteScanDone  = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCompleteScanDone",
            "(JII[I)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCompleteScanDone);*/

    /*Commented the FM RX Completescan functionality end*/


    _sMethodId_nativeCb_fmRxCmdGetFwVersion = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetFwVersion",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetFwVersion);

    _sMethodId_nativeCb_fmRxCmdIsValidChannel = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdIsValidChannel",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdIsValidChannel);


    _sMethodId_nativeCb_fmRxCmdGetCompleteScanProgress = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdGetCompleteScanProgress",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdGetCompleteScanProgress);

    _sMethodId_nativeCb_fmRxCmdStopCompleteScan = env->GetStaticMethodID(clazz,
            "nativeCb_fmRxCmdStopCompleteScan",
            "(JIIJ)V");
    VERIFY_METHOD_ID(_sMethodId_nativeCb_fmRxCmdStopCompleteScan);

    V4L2_JBTL_LOGD("nativeJFmRx_ClassInitNative:Exiting");
}

static JNINativeMethod JFmRxNative_sMethods[] = {
    /* name, signature, funcPtr */
    {"nativeJFmRx_ClassInitNative", "()V", (void*)nativeJFmRx_ClassInitNative},
    {"nativeJFmRx_Create", "(Lcom/ti/jfm/core/JFmContext;)I", (void*)nativeJFmRx_Create},
    {"nativeJFmRx_Destroy", "(J)I", (void*)nativeJFmRx_Destroy},
    {"nativeJFmRx_Enable", "(J)I", (void*)nativeJFmRx_Enable},
    {"nativeJFmRx_Disable", "(J)I", (void*)nativeJFmRx_Disable},
    {"nativeJFmRx_SetBand","(JI)I", (void*)nativeJFmRx_SetBand},
    {"nativeJFmRx_GetBand","(J)I", (void*)nativeJFmRx_GetBand},
    {"nativeJFmRx_Tune","(JI)I", (void*)nativeJFmRx_Tune},
    {"nativeJFmRx_GetTunedFrequency","(J)I", (void*)nativeJFmRx_GetTunedFrequency},
    {"nativeJFmRx_SetMonoStereoMode","(JI)I", (void*)nativeJFmRx_SetMonoStereoMode},
    {"nativeJFmRx_GetMonoStereoMode","(J)I", (void*)nativeJFmRx_GetMonoStereoMode},
    {"nativeJFmRx_SetMuteMode","(JI)I", (void*)nativeJFmRx_SetMuteMode},
    {"nativeJFmRx_GetMuteMode","(J)I", (void*)nativeJFmRx_GetMuteMode},
    {"nativeJFmRx_SetRssiThreshold","(JI)I", (void*)nativeJFmRx_SetRssiThreshold},
    {"nativeJFmRx_GetRssiThreshold","(J)I", (void*)nativeJFmRx_GetRssiThreshold},
    {"nativeJFmRx_GetRssi","(J)I", (void*)nativeJFmRx_GetRssi},
    {"nativeJFmRx_SetVolume","(JI)I", (void*)nativeJFmRx_SetVolume},
    {"nativeJFmRx_GetVolume","(J)I", (void*)nativeJFmRx_GetVolume},
    {"nativeJFmRx_SetChannelSpacing","(JI)I", (void*)nativeJFmRx_SetChannelSpacing},
    {"nativeJFmRx_GetChannelSpacing","(J)I", (void*)nativeJFmRx_GetChannelSpacing},
    {"nativeJFmRx_SetDeEmphasisFilter","(JI)I", (void*)nativeJFmRx_SetDeEmphasisFilter},
    {"nativeJFmRx_GetDeEmphasisFilter","(J)I", (void*)nativeJFmRx_GetDeEmphasisFilter},
    {"nativeJFmRx_Seek","(JI)I", (void*)nativeJFmRx_Seek},
    {"nativeJFmRx_StopSeek","(J)I", (void*)nativeJFmRx_StopSeek},
    {"nativeJFmRx_EnableRDS","(J)I", (void*)nativeJFmRx_EnableRDS},
    {"nativeJFmRx_DisableRDS","(J)I", (void*)nativeJFmRx_DisableRDS},
    {"nativeJFmRx_EnableAudioRouting","(J)I", (void*)nativeJFmRx_EnableAudioRouting},
    {"nativeJFmRx_DisableAudioRouting","(J)I", (void*)nativeJFmRx_DisableAudioRouting},
    {"nativeJFmRx_SetRdsAfSwitchMode","(JI)I", (void*)nativeJFmRx_SetRdsAfSwitchMode},
    {"nativeJFmRx_GetRdsAfSwitchMode","(J)I", (void*)nativeJFmRx_GetRdsAfSwitchMode},
    {"nativeJFmRx_ChangeAudioTarget","(JII)I",(void*)nativeJFmRx_ChangeAudioTarget},
    {"nativeJFmRx_ChangeDigitalTargetConfiguration","(JI)I",(void*)nativeJFmRx_ChangeDigitalTargetConfiguration},
    {"nativeJFmRx_SetRfDependentMuteMode","(JI)I",(void*)nativeJFmRx_SetRfDependentMuteMode},
    {"nativeJFmRx_GetRfDependentMute","(J)I",(void*)nativeJFmRx_GetRfDependentMute},
    {"nativeJFmRx_SetRdsSystem","(JI)I",(void*)nativeJFmRx_SetRdsSystem},
    {"nativeJFmRx_GetRdsSystem","(J)I",(void*)nativeJFmRx_GetRdsSystem},
    {"nativeJFmRx_SetRdsGroupMask","(JJ)I",(void*)nativeJFmRx_SetRdsGroupMask},
    {"nativeJFmRx_GetRdsGroupMask","(J)I",(void*)nativeJFmRx_GetRdsGroupMask},
    {"nativeJFmRx_CompleteScan","(J)I",(void*)nativeJFmRx_CompleteScan},
    {"nativeJFmRx_IsValidChannel","(J)I",(void*)nativeJFmRx_IsValidChannel},
    {"nativeJFmRx_GetFwVersion","(J)I",(void*)nativeJFmRx_GetFwVersion},
    {"nativeJFmRx_GetCompleteScanProgress","(J)I",(void*)nativeJFmRx_GetCompleteScanProgress},
    {"nativeJFmRx_StopCompleteScan","(J)I",(void*)nativeJFmRx_StopCompleteScan},

};

/**********************************/


/*
 * Register several native methods for one class.
 */
static int registerNatives(JNIEnv* env, const char* className,
               JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;

    clazz = env->FindClass(className);
    if (clazz == NULL) {
         V4L2_JBTL_LOGD("Can not find class %s\n", className);
        return JNI_FALSE;
    }

    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        V4L2_JBTL_LOGD("Can not RegisterNatives\n");
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

/*Commented the FM TX functionality start*/

extern JNINativeMethod JFmTxNative_sMethods[];
extern int getTxNativeSize();

/*Commented the FM TX functionality end*/

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;

    V4L2_JBTL_LOGD("OnLoad");

    if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
        goto bail;
    }

    if (!registerNatives(env,
                 "com/ti/jfm/core/JFmRx",
                         JFmRxNative_sMethods,
                 NELEM(JFmRxNative_sMethods))) {
        goto bail;
    }


    if (!registerNatives(env,
                 "com/ti/jfm/core/JFmTx",
                         JFmTxNative_sMethods,
                 getTxNativeSize())) {
        goto bail;
    }


    env->GetJavaVM(&g_jVM);

    /* success -- return valid version number */
    result = JNI_VERSION_1_4;

bail:
    return result;
}