diff options
author | Venkateshwarlu Domakonda <Venkateshwarlu@codeaurora.org> | 2013-03-25 16:53:03 +0530 |
---|---|---|
committer | Venkateshwarlu Domakonda <Venkateshwarlu@codeaurora.org> | 2013-03-25 19:07:22 +0530 |
commit | aa25363e9c44e916d469dcb21f43e826e660d8d9 (patch) | |
tree | f42b331d26567bede949430ee66ef2bc9c88bb97 /jni | |
parent | 371d637753718494c6e4ae0bf72424d662766e77 (diff) | |
download | android_hardware_qcom_fm-aa25363e9c44e916d469dcb21f43e826e660d8d9.tar.gz android_hardware_qcom_fm-aa25363e9c44e916d469dcb21f43e826e660d8d9.tar.bz2 android_hardware_qcom_fm-aa25363e9c44e916d469dcb21f43e826e660d8d9.zip |
FM: Migrate FM Framework code base to new git
Change-Id: I4769b2381fc62d75e67c428071c320b8f63cce0e
Diffstat (limited to 'jni')
-rw-r--r-- | jni/Android.mk | 25 | ||||
-rw-r--r-- | jni/android_hardware_fm.cpp | 818 |
2 files changed, 843 insertions, 0 deletions
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; +} |