FM: Migrate FM Framework code base to new git

Change-Id: I4769b2381fc62d75e67c428071c320b8f63cce0e
diff --git a/jni/Android.mk b/jni/Android.mk
new file mode 100644
index 0000000..594332f
--- /dev/null
+++ b/jni/Android.mk
@@ -0,0 +1,25 @@
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+android_hardware_fm.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+        libnativehelper \
+        libcutils
+
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
+LOCAL_CFLAGS += -include bionic/libc/kernel/arch-arm/asm/posix_types.h
+LOCAL_CFLAGS += -include bionic/libc/kernel/arch-arm/asm/byteorder.h
+LOCAL_CFLAGS += -include bionic/libc/kernel/common/linux/types.h
+LOCAL_CFLAGS += -include bionic/libc/kernel/common/linux/posix_types.h
+LOCAL_CFLAGS += -include bionic/libc/kernel/common/linux/socket.h
+
+LOCAL_MODULE := libqcomfm_jni
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+endif # is-vendor-board-platform
diff --git a/jni/android_hardware_fm.cpp b/jni/android_hardware_fm.cpp
new file mode 100644
index 0000000..7068b83
--- /dev/null
+++ b/jni/android_hardware_fm.cpp
@@ -0,0 +1,818 @@
+/*
+ * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *            notice, this list of conditions and the following disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyright
+ *            notice, this list of conditions and the following disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "fmradio"
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "utils/Log.h"
+#include "utils/misc.h"
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <media/tavarua.h>
+#include <linux/videodev2.h>
+#include <math.h>
+
+#define RADIO "/dev/radio0"
+#define FM_JNI_SUCCESS 0L
+#define FM_JNI_FAILURE -1L
+#define SEARCH_DOWN 0
+#define SEARCH_UP 1
+#define TUNE_MULT 16000
+#define HIGH_BAND 2
+#define LOW_BAND  1
+#define CAL_DATA_SIZE 23
+#define V4L2_CTRL_CLASS_USER 0x00980000
+#define V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION           (V4L2_CTRL_CLASS_USER + 0x92A)
+#define V4L2_CID_PRIVATE_TAVARUA_ON_CHANNEL_THRESHOLD   (V4L2_CTRL_CLASS_USER + 0x92B)
+#define V4L2_CID_PRIVATE_TAVARUA_OFF_CHANNEL_THRESHOLD  (V4L2_CTRL_CLASS_USER + 0x92C)
+#define TX_RT_LENGTH       63
+#define WAIT_TIMEOUT 200000 /* 200*1000us */
+#define TX_RT_DELIMITER    0x0d
+#define PS_LEN    9
+#define STD_BUF_SIZE 256
+enum search_dir_t {
+    SEEK_UP,
+    SEEK_DN,
+    SCAN_UP,
+    SCAN_DN
+};
+
+
+using namespace android;
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_acquireFdNative
+        (JNIEnv* env, jobject thiz, jstring path)
+{
+    int fd;
+    int i, retval=0, err;
+    char value[PROPERTY_VALUE_MAX] = {'\0'};
+    char versionStr[40] = {'\0'};
+    int init_success = 0;
+    jboolean isCopy;
+    v4l2_capability cap;
+    const char* radio_path = env->GetStringUTFChars(path, &isCopy);
+    if(radio_path == NULL){
+        return FM_JNI_FAILURE;
+    }
+    fd = open(radio_path, O_RDONLY, O_NONBLOCK);
+    if(isCopy == JNI_TRUE){
+        env->ReleaseStringUTFChars(path, radio_path);
+    }
+    if(fd < 0){
+        return FM_JNI_FAILURE;
+    }
+    //Read the driver verions
+    err = ioctl(fd, VIDIOC_QUERYCAP, &cap);
+
+    ALOGD("VIDIOC_QUERYCAP returns :%d: version: %d \n", err , cap.version );
+
+    if( err >= 0 ) {
+       ALOGD("Driver Version(Same as ChipId): %x \n",  cap.version );
+       /*Conver the integer to string */
+       sprintf(versionStr, "%d", cap.version );
+       property_set("hw.fm.version", versionStr);
+    } else {
+       return FM_JNI_FAILURE;
+    }
+    /*Set the mode for soc downloader*/
+    property_set("hw.fm.mode", "normal");
+    /* Need to clear the hw.fm.init firstly */
+    property_set("hw.fm.init", "0");
+    property_set("ctl.start", "fm_dl");
+    sched_yield();
+    for(i=0; i<45; i++) {
+        property_get("hw.fm.init", value, NULL);
+        if (strcmp(value, "1") == 0) {
+            init_success = 1;
+            break;
+        } else {
+            usleep(WAIT_TIMEOUT);
+        }
+    }
+    ALOGE("init_success:%d after %f seconds \n", init_success, 0.2*i);
+    if(!init_success) {
+        property_set("ctl.stop", "fm_dl");
+       // close the fd(power down)
+
+       close(fd);
+        return FM_JNI_FAILURE;
+    }
+    return fd;
+}
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_closeFdNative
+    (JNIEnv * env, jobject thiz, jint fd)
+{
+    int i = 0;
+    int cleanup_success = 0;
+    char value = 0, retval =0;
+
+    property_set("ctl.stop", "fm_dl");
+    close(fd);
+    return FM_JNI_SUCCESS;
+}
+
+/********************************************************************
+ * Current JNI
+ *******************************************************************/
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_getFreqNative
+    (JNIEnv * env, jobject thiz, jint fd)
+{
+    int err;
+    struct v4l2_frequency freq;
+    freq.type = V4L2_TUNER_RADIO;
+    err = ioctl(fd, VIDIOC_G_FREQUENCY, &freq);
+    if(err < 0){
+      return FM_JNI_FAILURE;
+    }
+    return ((freq.frequency*1000)/TUNE_MULT);
+}
+
+/*native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_setFreqNative
+    (JNIEnv * env, jobject thiz, jint fd, jint freq)
+{
+    int err;
+    double tune;
+    struct v4l2_frequency freq_struct;
+    freq_struct.type = V4L2_TUNER_RADIO;
+    freq_struct.frequency = (freq*TUNE_MULT/1000);
+    err = ioctl(fd, VIDIOC_S_FREQUENCY, &freq_struct);
+    if(err < 0){
+            return FM_JNI_FAILURE;
+    }
+    return FM_JNI_SUCCESS;
+}
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_setControlNative
+    (JNIEnv * env, jobject thiz, jint fd, jint id, jint value)
+{
+    struct v4l2_control control;
+    int i;
+    int err;
+    ALOGE("id(%x) value: %x\n", id, value);
+    control.value = value;
+
+    control.id = id;
+    for(i=0;i<3;i++) {
+        err = ioctl(fd,VIDIOC_S_CTRL,&control);
+        if(err >= 0){
+            return FM_JNI_SUCCESS;
+        }
+    }
+    ALOGE("setControl native returned with err %d", err);
+    return FM_JNI_FAILURE;
+}
+
+static jint android_hardware_fmradio_FmReceiverJNI_SetCalibrationNative
+     (JNIEnv * env, jobject thiz, jint fd, jbyteArray buff)
+{
+
+    struct v4l2_ext_control ext_ctl;
+    char tmp[CAL_DATA_SIZE] = {0x00};
+    int err;
+    FILE* cal_file;
+
+    cal_file = fopen("/data/app/Riva_fm_cal", "r" );
+    if(cal_file != NULL) {
+        ext_ctl.id = V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION;
+        if (fread(&tmp[0],1,CAL_DATA_SIZE,cal_file) < CAL_DATA_SIZE)
+        {
+            ALOGE("File read failed");
+            return FM_JNI_FAILURE;
+        }
+        ext_ctl.string = tmp;
+        ext_ctl.size = CAL_DATA_SIZE;
+        struct v4l2_ext_controls v4l2_ctls;
+
+        v4l2_ctls.ctrl_class = V4L2_CTRL_CLASS_USER,
+        v4l2_ctls.count   = 1,
+        v4l2_ctls.controls  = &ext_ctl;
+        err = ioctl(fd, VIDIOC_S_EXT_CTRLS, &v4l2_ctls );
+        if(err >= 0){
+            return FM_JNI_SUCCESS;
+        }
+    }else {
+        return FM_JNI_SUCCESS;
+    }
+  return FM_JNI_SUCCESS;
+}
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_getControlNative
+    (JNIEnv * env, jobject thiz, jint fd, jint id)
+{
+    struct v4l2_control control;
+    int err;
+    ALOGE("id(%x)\n", id);
+
+    control.id = id;
+    err = ioctl(fd,VIDIOC_G_CTRL,&control);
+    if(err < 0){
+        return FM_JNI_FAILURE;
+    }
+    return control.value;
+}
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_startSearchNative
+    (JNIEnv * env, jobject thiz, jint fd, jint dir)
+{
+    ALOGE("startSearchNative: Issuing the VIDIOC_S_HW_FREQ_SEEK");
+    struct v4l2_hw_freq_seek hw_seek;
+    int err;
+    hw_seek.seek_upward = dir;
+    hw_seek.type = V4L2_TUNER_RADIO;
+    err = ioctl(fd,VIDIOC_S_HW_FREQ_SEEK,&hw_seek);
+    if(err < 0){
+        ALOGE("startSearchNative: ioctl failed!!! with error %d\n", err);
+        return FM_JNI_FAILURE;
+    } else
+        ALOGE("startSearchNative: ioctl succedded!!!");
+    return FM_JNI_SUCCESS;
+}
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_cancelSearchNative
+    (JNIEnv * env, jobject thiz, jint fd)
+{
+    struct v4l2_control control;
+    int err;
+    control.id=V4L2_CID_PRIVATE_TAVARUA_SRCHON;
+    control.value=0;
+    err = ioctl(fd,VIDIOC_S_CTRL,&control);
+    if(err < 0){
+        return FM_JNI_FAILURE;
+    }
+    return FM_JNI_SUCCESS;
+}
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_getRSSINative
+    (JNIEnv * env, jobject thiz, jint fd)
+{
+    struct v4l2_tuner tuner;
+    int err;
+
+    tuner.index = 0;
+    tuner.signal = 0;
+    err = ioctl(fd, VIDIOC_G_TUNER, &tuner);
+    if(err < 0){
+        return FM_JNI_FAILURE;
+    }
+    return tuner.signal;
+}
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_setBandNative
+    (JNIEnv * env, jobject thiz, jint fd, jint low, jint high)
+{
+    struct v4l2_tuner tuner;
+    int err;
+
+    tuner.index = 0;
+    tuner.signal = 0;
+    tuner.rangelow = low * (TUNE_MULT/1000);
+    tuner.rangehigh = high * (TUNE_MULT/1000);
+    err = ioctl(fd, VIDIOC_S_TUNER, &tuner);
+    if(err < 0){
+        return FM_JNI_FAILURE;
+    }
+    return FM_JNI_SUCCESS;
+}
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_getLowerBandNative
+    (JNIEnv * env, jobject thiz, jint fd)
+{
+    struct v4l2_tuner tuner;
+    int err;
+    tuner.index = 0;
+
+    err = ioctl(fd, VIDIOC_G_TUNER, &tuner);
+    if(err < 0){
+        ALOGE("low_band value: <%x> \n", tuner.rangelow);
+        return FM_JNI_FAILURE;
+    }
+    return ((tuner.rangelow * 1000)/ TUNE_MULT);
+}
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_getUpperBandNative
+    (JNIEnv * env, jobject thiz, jint fd)
+{
+    struct v4l2_tuner tuner;
+    int err;
+    tuner.index = 0;
+
+    err = ioctl(fd, VIDIOC_G_TUNER, &tuner);
+    if(err < 0){
+        ALOGE("high_band value: <%x> \n", tuner.rangehigh);
+        return FM_JNI_FAILURE;
+    }
+    return ((tuner.rangehigh * 1000) / TUNE_MULT);
+}
+
+static jint android_hardware_fmradio_FmReceiverJNI_setMonoStereoNative
+    (JNIEnv * env, jobject thiz, jint fd, jint val)
+{
+
+    struct v4l2_tuner tuner;
+    int err;
+
+    tuner.index = 0;
+    err = ioctl(fd, VIDIOC_G_TUNER, &tuner);
+
+    if(err < 0)
+        return FM_JNI_FAILURE;
+
+    tuner.audmode = val;
+    err = ioctl(fd, VIDIOC_S_TUNER, &tuner);
+
+    if(err < 0)
+        return FM_JNI_FAILURE;
+
+    return FM_JNI_SUCCESS;
+
+}
+
+
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_getBufferNative
+ (JNIEnv * env, jobject thiz, jint fd, jbooleanArray buff, jint index)
+{
+    int err;
+    jboolean isCopy;
+    struct v4l2_requestbuffers reqbuf;
+    struct v4l2_buffer v4l2_buf;
+    memset(&reqbuf, 0, sizeof (reqbuf));
+    enum v4l2_buf_type type = V4L2_BUF_TYPE_PRIVATE;
+    reqbuf.type = V4L2_BUF_TYPE_PRIVATE;
+    reqbuf.memory = V4L2_MEMORY_USERPTR;
+    jboolean *bool_buffer = env->GetBooleanArrayElements(buff,&isCopy);
+    memset(&v4l2_buf, 0, sizeof (v4l2_buf));
+    v4l2_buf.index = index;
+    v4l2_buf.type = type;
+    v4l2_buf.length = STD_BUF_SIZE;
+    v4l2_buf.m.userptr = (unsigned long)bool_buffer;
+    err = ioctl(fd,VIDIOC_DQBUF,&v4l2_buf);
+    if(err < 0){
+        /* free up the memory in failure case*/
+        env->ReleaseBooleanArrayElements(buff, bool_buffer, 0);
+        return FM_JNI_FAILURE;
+    }
+
+    /* Always copy buffer and free up the memory */
+    env->ReleaseBooleanArrayElements(buff, bool_buffer, 0);
+
+    return v4l2_buf.bytesused;
+}
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_getRawRdsNative
+ (JNIEnv * env, jobject thiz, jint fd, jbooleanArray buff, jint count)
+{
+
+    return (read (fd, buff, count));
+
+}
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_setNotchFilterNative(JNIEnv * env, jobject thiz,jint fd, jint id, jboolean aValue)
+{
+    char value[PROPERTY_VALUE_MAX] = {'\0'};
+    int init_success = 0,i;
+    char notch[20] = {0x00};
+    struct v4l2_control control;
+    int err;
+    /*Enable/Disable the WAN avoidance*/
+    property_set("hw.fm.init", "0");
+    if (aValue)
+       property_set("hw.fm.mode", "wa_enable");
+    else
+       property_set("hw.fm.mode", "wa_disable");
+
+    property_set("ctl.start", "fm_dl");
+    sched_yield();
+    for(i=0; i<10; i++) {
+       property_get("hw.fm.init", value, NULL);
+       if (strcmp(value, "1") == 0) {
+          init_success = 1;
+          break;
+       } else {
+          usleep(WAIT_TIMEOUT);
+       }
+    }
+    ALOGE("init_success:%d after %f seconds \n", init_success, 0.2*i);
+
+    property_get("notch.value", notch, NULL);
+    ALOGE("Notch = %s",notch);
+    if (!strncmp("HIGH",notch,strlen("HIGH")))
+        control.value = HIGH_BAND;
+    else if(!strncmp("LOW",notch,strlen("LOW")))
+        control.value = LOW_BAND;
+    else
+        control.value = 0;
+
+    ALOGE("Notch value : %d", control.value);
+    control.id = id;
+    err = ioctl(fd, VIDIOC_S_CTRL,&control );
+    if(err < 0){
+          return FM_JNI_FAILURE;
+    }
+    return FM_JNI_SUCCESS;
+}
+
+
+/* native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_setAnalogModeNative(JNIEnv * env, jobject thiz, jboolean aValue)
+{
+    int i=0;
+    char value[PROPERTY_VALUE_MAX] = {'\0'};
+    char firmwareVersion[80];
+
+    /*Enable/Disable Analog Mode FM*/
+    property_set("hw.fm.init", "0");
+    if (aValue) {
+        property_set("hw.fm.isAnalog", "true");
+    } else {
+        property_set("hw.fm.isAnalog", "false");
+    }
+    property_set("hw.fm.mode","config_dac");
+    property_set("ctl.start", "fm_dl");
+    sched_yield();
+    for(i=0; i<10; i++) {
+       property_get("hw.fm.init", value, NULL);
+       if (strcmp(value, "1") == 0) {
+          return 1;
+       } else {
+          usleep(WAIT_TIMEOUT);
+       }
+    }
+
+    return 0;
+}
+
+
+
+
+/*
+ * Interfaces added for Tx
+*/
+
+/*native interface */
+static jint android_hardware_fmradio_FmReceiverJNI_setPTYNative
+    (JNIEnv * env, jobject thiz, jint fd, jint pty)
+{
+    ALOGE("->android_hardware_fmradio_FmReceiverJNI_setPTYNative\n");
+    struct v4l2_control control;
+
+    control.id = V4L2_CID_RDS_TX_PTY;
+    control.value = pty & MASK_PTY;
+
+    int err;
+    err = ioctl(fd, VIDIOC_S_CTRL,&control );
+    if(err < 0){
+            return FM_JNI_FAILURE;
+    }
+    return FM_JNI_SUCCESS;
+}
+
+static jint android_hardware_fmradio_FmReceiverJNI_setPINative
+    (JNIEnv * env, jobject thiz, jint fd, jint pi)
+{
+    ALOGE("->android_hardware_fmradio_FmReceiverJNI_setPINative\n");
+
+    struct v4l2_control control;
+
+    control.id = V4L2_CID_RDS_TX_PI;
+    control.value = pi & MASK_PI;
+
+    int err;
+    err = ioctl(fd, VIDIOC_S_CTRL,&control );
+    if(err < 0){
+		ALOGE("->pty native failed");
+            return FM_JNI_FAILURE;
+    }
+
+    return FM_JNI_SUCCESS;
+}
+
+static jint android_hardware_fmradio_FmReceiverJNI_startRTNative
+    (JNIEnv * env, jobject thiz, jint fd, jstring radio_text, jint count )
+{
+    ALOGD("->android_hardware_fmradio_FmReceiverJNI_startRTNative\n");
+
+    struct v4l2_ext_control ext_ctl;
+    struct v4l2_ext_controls v4l2_ctls;
+
+    int err = 0;
+    jboolean isCopy = false;
+    char* rt_string1 = NULL;
+    char* rt_string = (char*)env->GetStringUTFChars(radio_text, &isCopy);
+    if(rt_string == NULL ){
+        ALOGE("RT string is not valid \n");
+        return FM_JNI_FAILURE;
+    }
+
+    rt_string1 = (char*) malloc(TX_RT_LENGTH + 1);
+    if (rt_string1 == NULL) {
+       ALOGE("out of memory \n");
+       env->ReleaseStringUTFChars(radio_text, rt_string);
+       return FM_JNI_FAILURE;
+    }
+    memset (rt_string1, 0, TX_RT_LENGTH + 1);
+    memcpy(rt_string1, rt_string, count);
+
+    if(count < TX_RT_LENGTH)
+       rt_string1[count] = TX_RT_DELIMITER;
+
+    ext_ctl.id     = V4L2_CID_RDS_TX_RADIO_TEXT;
+    ext_ctl.string = rt_string1;
+    ext_ctl.size   = strlen(rt_string1) + 1;
+
+    /* form the ctrls data struct */
+    v4l2_ctls.ctrl_class = V4L2_CTRL_CLASS_FM_TX,
+    v4l2_ctls.count      = 1,
+    v4l2_ctls.controls   = &ext_ctl;
+
+
+    err = ioctl(fd, VIDIOC_S_EXT_CTRLS, &v4l2_ctls );
+    env->ReleaseStringUTFChars(radio_text, rt_string);
+    if (rt_string1 != NULL) {
+        free(rt_string1);
+        rt_string1 = NULL;
+    }
+    if(err < 0){
+        ALOGE("VIDIOC_S_EXT_CTRLS for start RT returned : %d\n", err);
+        return FM_JNI_FAILURE;
+    }
+
+    ALOGD("->android_hardware_fmradio_FmReceiverJNI_startRTNative is SUCCESS\n");
+    return FM_JNI_SUCCESS;
+}
+
+static jint android_hardware_fmradio_FmReceiverJNI_stopRTNative
+    (JNIEnv * env, jobject thiz, jint fd )
+{
+    ALOGE("->android_hardware_fmradio_FmReceiverJNI_stopRTNative\n");
+    int err;
+    struct v4l2_control control;
+    control.id = V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_RT;
+
+    err = ioctl(fd, VIDIOC_S_CTRL , &control);
+    if(err < 0){
+            return FM_JNI_FAILURE;
+    }
+    ALOGE("->android_hardware_fmradio_FmReceiverJNI_stopRTNative is SUCCESS\n");
+    return FM_JNI_SUCCESS;
+}
+
+static jint android_hardware_fmradio_FmReceiverJNI_startPSNative
+    (JNIEnv * env, jobject thiz, jint fd, jstring buff, jint count )
+{
+    ALOGD("->android_hardware_fmradio_FmReceiverJNI_startPSNative\n");
+
+    struct v4l2_ext_control ext_ctl;
+    struct v4l2_ext_controls v4l2_ctls;
+    int l;
+    int err = 0;
+    jboolean isCopy = false;
+    char *ps_copy = NULL;
+    const char *ps_string = NULL;
+
+    ps_string = env->GetStringUTFChars(buff, &isCopy);
+    if (ps_string != NULL) {
+        l = strlen(ps_string);
+        if ((l > 0) && ((l + 1) == PS_LEN)) {
+             ps_copy = (char *)malloc(sizeof(char) * PS_LEN);
+             if (ps_copy != NULL) {
+                 memset(ps_copy, '\0', PS_LEN);
+                 memcpy(ps_copy, ps_string, (PS_LEN - 1));
+             } else {
+                 env->ReleaseStringUTFChars(buff, ps_string);
+                 return FM_JNI_FAILURE;
+             }
+        } else {
+             env->ReleaseStringUTFChars(buff, ps_string);
+             return FM_JNI_FAILURE;
+        }
+    } else {
+        return FM_JNI_FAILURE;
+    }
+
+    env->ReleaseStringUTFChars(buff, ps_string);
+
+    ext_ctl.id     = V4L2_CID_RDS_TX_PS_NAME;
+    ext_ctl.string = ps_copy;
+    ext_ctl.size   = PS_LEN;
+
+    /* form the ctrls data struct */
+    v4l2_ctls.ctrl_class = V4L2_CTRL_CLASS_FM_TX,
+    v4l2_ctls.count      = 1,
+    v4l2_ctls.controls   = &ext_ctl;
+
+    err = ioctl(fd, VIDIOC_S_EXT_CTRLS, &v4l2_ctls);
+    if (err < 0) {
+        ALOGE("VIDIOC_S_EXT_CTRLS for Start PS returned : %d\n", err);
+        free(ps_copy);
+        return FM_JNI_FAILURE;
+    }
+
+    ALOGD("->android_hardware_fmradio_FmReceiverJNI_startPSNative is SUCCESS\n");
+    free(ps_copy);
+
+    return FM_JNI_SUCCESS;
+}
+
+static jint android_hardware_fmradio_FmReceiverJNI_stopPSNative
+    (JNIEnv * env, jobject thiz, jint fd)
+{
+    ALOGE("->android_hardware_fmradio_FmReceiverJNI_stopPSNative\n");
+    struct v4l2_control control;
+    control.id = V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_PS_NAME;
+
+    int err;
+    err = ioctl(fd, VIDIOC_S_CTRL , &control);
+    if(err < 0){
+            return FM_JNI_FAILURE;
+    }
+    ALOGE("->android_hardware_fmradio_FmReceiverJNI_stopPSNative is SUCCESS\n");
+    return FM_JNI_SUCCESS;
+}
+
+static jint android_hardware_fmradio_FmReceiverJNI_configureSpurTable
+    (JNIEnv * env, jobject thiz, jint fd)
+{
+    ALOGD("->android_hardware_fmradio_FmReceiverJNI_configureSpurTable\n");
+    int retval = 0;
+    struct v4l2_control control;
+
+    control.id = V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE;
+    retval = ioctl(fd, VIDIOC_S_CTRL, &control);
+    if (retval < 0) {
+            ALOGE("configureSpurTable: Failed to Write the SPUR Table\n");
+            return FM_JNI_FAILURE;
+    } else
+            ALOGD("configureSpurTable: SPUR Table Configuration successful\n");
+
+    return FM_JNI_SUCCESS;
+}
+
+static jint android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative
+    (JNIEnv * env, jobject thiz, jint fd, jint repCount)
+{
+    ALOGE("->android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative\n");
+
+    struct v4l2_control control;
+
+    control.id = V4L2_CID_PRIVATE_TAVARUA_TX_SETPSREPEATCOUNT;
+    control.value = repCount & MASK_TXREPCOUNT;
+
+    int err;
+    err = ioctl(fd, VIDIOC_S_CTRL,&control );
+    if(err < 0){
+            return FM_JNI_FAILURE;
+    }
+
+    ALOGE("->android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative is SUCCESS\n");
+    return FM_JNI_SUCCESS;
+}
+
+static jint android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative
+    (JNIEnv * env, jobject thiz, jint fd, jint powLevel)
+{
+    ALOGE("->android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative\n");
+
+    struct v4l2_control control;
+
+    control.id = V4L2_CID_TUNE_POWER_LEVEL;
+    control.value = powLevel;
+
+    int err;
+    err = ioctl(fd, VIDIOC_S_CTRL,&control );
+    if(err < 0){
+            return FM_JNI_FAILURE;
+    }
+
+    ALOGE("->android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative is SUCCESS\n");
+    return FM_JNI_SUCCESS;
+}
+
+/*
+ * JNI registration.
+ */
+static JNINativeMethod gMethods[] = {
+        /* name, signature, funcPtr */
+        { "acquireFdNative", "(Ljava/lang/String;)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_acquireFdNative},
+        { "closeFdNative", "(I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_closeFdNative},
+        { "getFreqNative", "(I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_getFreqNative},
+        { "setFreqNative", "(II)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_setFreqNative},
+        { "getControlNative", "(II)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_getControlNative},
+        { "setControlNative", "(III)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_setControlNative},
+        { "startSearchNative", "(II)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_startSearchNative},
+        { "cancelSearchNative", "(I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_cancelSearchNative},
+        { "getRSSINative", "(I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_getRSSINative},
+        { "setBandNative", "(III)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_setBandNative},
+        { "getLowerBandNative", "(I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_getLowerBandNative},
+        { "getUpperBandNative", "(I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_getUpperBandNative},
+        { "getBufferNative", "(I[BI)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_getBufferNative},
+        { "setMonoStereoNative", "(II)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_setMonoStereoNative},
+        { "getRawRdsNative", "(I[BI)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_getRawRdsNative},
+       { "setNotchFilterNative", "(IIZ)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_setNotchFilterNative},
+        { "startRTNative", "(ILjava/lang/String;I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_startRTNative},
+        { "stopRTNative", "(I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_stopRTNative},
+        { "startPSNative", "(ILjava/lang/String;I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_startPSNative},
+        { "stopPSNative", "(I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_stopPSNative},
+        { "setPTYNative", "(II)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_setPTYNative},
+        { "setPINative", "(II)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_setPINative},
+        { "setPSRepeatCountNative", "(II)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative},
+        { "setTxPowerLevelNative", "(II)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative},
+       { "setAnalogModeNative", "(Z)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_setAnalogModeNative},
+        { "SetCalibrationNative", "(I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_SetCalibrationNative},
+        { "configureSpurTable", "(I)I",
+            (void*)android_hardware_fmradio_FmReceiverJNI_configureSpurTable},
+
+};
+
+int register_android_hardware_fm_fmradio(JNIEnv* env)
+{
+        return jniRegisterNativeMethods(env, "qcom/fmradio/FmReceiverJNI", gMethods, NELEM(gMethods));
+}
+
+jint JNI_OnLoad(JavaVM *jvm, void *reserved)
+{
+  JNIEnv *e;
+  int status;
+   ALOGE("FM : loading QCOMM FM-JNI\n");
+  
+   if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
+       ALOGE("JNI version mismatch error");
+      return JNI_ERR;
+   }
+
+   if ((status = register_android_hardware_fm_fmradio(e)) < 0) {
+       ALOGE("jni adapter service registration failure, status: %d", status);
+      return JNI_ERR;
+   }
+   return JNI_VERSION_1_6;
+}