Home | History | Annotate | Download | only in fmr
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <jni.h>
     18 #include "fmr.h"
     19 
     20 #ifdef LOG_TAG
     21 #undef LOG_TAG
     22 #endif
     23 #define LOG_TAG "FMLIB_JNI"
     24 
     25 static int g_idx = -1;
     26 extern struct fmr_ds fmr_data;
     27 
     28 jboolean openDev(JNIEnv *env, jobject thiz)
     29 {
     30     int ret = 0;
     31 
     32     ret = FMR_open_dev(g_idx); // if success, then ret = 0; else ret < 0
     33 
     34     LOGD("%s, [ret=%d]\n", __func__, ret);
     35     return ret?JNI_FALSE:JNI_TRUE;
     36 }
     37 
     38 jboolean closeDev(JNIEnv *env, jobject thiz)
     39 {
     40     int ret = 0;
     41 
     42     ret = FMR_close_dev(g_idx);
     43 
     44     LOGD("%s, [ret=%d]\n", __func__, ret);
     45     return ret?JNI_FALSE:JNI_TRUE;
     46 }
     47 
     48 jboolean powerUp(JNIEnv *env, jobject thiz, jfloat freq)
     49 {
     50     int ret = 0;
     51     int tmp_freq;
     52 
     53     LOGI("%s, [freq=%d]\n", __func__, (int)freq);
     54     tmp_freq = (int)(freq * 10);        //Eg, 87.5 * 10 --> 875
     55     ret = FMR_pwr_up(g_idx, tmp_freq);
     56 
     57     LOGD("%s, [ret=%d]\n", __func__, ret);
     58     return ret?JNI_FALSE:JNI_TRUE;
     59 }
     60 
     61 jboolean powerDown(JNIEnv *env, jobject thiz, jint type)
     62 {
     63     int ret = 0;
     64 
     65     ret = FMR_pwr_down(g_idx, type);
     66 
     67     LOGD("%s, [ret=%d]\n", __func__, ret);
     68     return ret?JNI_FALSE:JNI_TRUE;
     69 }
     70 
     71 jboolean tune(JNIEnv *env, jobject thiz, jfloat freq)
     72 {
     73     int ret = 0;
     74     int tmp_freq;
     75 
     76     tmp_freq = (int)(freq * 10);        //Eg, 87.5 * 10 --> 875
     77     ret = FMR_tune(g_idx, tmp_freq);
     78 
     79     LOGD("%s, [ret=%d]\n", __func__, ret);
     80     return ret?JNI_FALSE:JNI_TRUE;
     81 }
     82 
     83 jfloat seek(JNIEnv *env, jobject thiz, jfloat freq, jboolean isUp) //jboolean isUp;
     84 {
     85     int ret = 0;
     86     int tmp_freq;
     87     int ret_freq;
     88     float val;
     89 
     90     tmp_freq = (int)(freq * 100);       //Eg, 87.55 * 100 --> 8755
     91     ret = FMR_set_mute(g_idx, 1);
     92     if (ret) {
     93         LOGE("%s, error, [ret=%d]\n", __func__, ret);
     94     }
     95     LOGD("%s, [mute] [ret=%d]\n", __func__, ret);
     96 
     97     ret = FMR_seek(g_idx, tmp_freq, (int)isUp, &ret_freq);
     98     if (ret) {
     99         ret_freq = tmp_freq; //seek error, so use original freq
    100     }
    101 
    102     LOGD("%s, [freq=%d] [ret=%d]\n", __func__, ret_freq, ret);
    103 
    104     val = (float)ret_freq/100;   //Eg, 8755 / 100 --> 87.55
    105 
    106     return val;
    107 }
    108 
    109 jshortArray autoScan(JNIEnv *env, jobject thiz)
    110 {
    111 #define FM_SCAN_CH_SIZE_MAX 200
    112     int ret = 0;
    113     jshortArray scanChlarray;
    114     int chl_cnt = FM_SCAN_CH_SIZE_MAX;
    115     uint16_t ScanTBL[FM_SCAN_CH_SIZE_MAX];
    116 
    117     LOGI("%s, [tbl=%p]\n", __func__, ScanTBL);
    118     FMR_Pre_Search(g_idx);
    119     ret = FMR_scan(g_idx, ScanTBL, &chl_cnt);
    120     if (ret < 0) {
    121         LOGE("scan failed!\n");
    122         scanChlarray = NULL;
    123         goto out;
    124     }
    125     if (chl_cnt > 0) {
    126         scanChlarray = env->NewShortArray(chl_cnt);
    127         env->SetShortArrayRegion(scanChlarray, 0, chl_cnt, (const jshort*)&ScanTBL[0]);
    128     } else {
    129         LOGE("cnt error, [cnt=%d]\n", chl_cnt);
    130         scanChlarray = NULL;
    131     }
    132     FMR_Restore_Search(g_idx);
    133 
    134     if (fmr_data.scan_stop == fm_true) {
    135         ret = FMR_tune(g_idx, fmr_data.cur_freq);
    136         LOGI("scan stop!!! tune ret=%d",ret);
    137         scanChlarray = NULL;
    138         ret = -1;
    139     }
    140 
    141 out:
    142     LOGD("%s, [cnt=%d] [ret=%d]\n", __func__, chl_cnt, ret);
    143     return scanChlarray;
    144 }
    145 
    146 jshort readRds(JNIEnv *env, jobject thiz)
    147 {
    148     int ret = 0;
    149     uint16_t status = 0;
    150 
    151     ret = FMR_read_rds_data(g_idx, &status);
    152 
    153     if (ret) {
    154         //LOGE("%s,status = 0,[ret=%d]\n", __func__, ret);
    155         status = 0; //there's no event or some error happened
    156     }
    157 
    158     return status;
    159 }
    160 
    161 jbyteArray getPs(JNIEnv *env, jobject thiz)
    162 {
    163     int ret = 0;
    164     jbyteArray PSname;
    165     uint8_t *ps = NULL;
    166     int ps_len = 0;
    167 
    168     ret = FMR_get_ps(g_idx, &ps, &ps_len);
    169     if (ret) {
    170         LOGE("%s, error, [ret=%d]\n", __func__, ret);
    171         return NULL;
    172     }
    173     PSname = env->NewByteArray(ps_len);
    174     env->SetByteArrayRegion(PSname, 0, ps_len, (const jbyte*)ps);
    175     LOGD("%s, [ret=%d]\n", __func__, ret);
    176     return PSname;
    177 }
    178 
    179 jbyteArray getLrText(JNIEnv *env, jobject thiz)
    180 {
    181     int ret = 0;
    182     jbyteArray LastRadioText;
    183     uint8_t *rt = NULL;
    184     int rt_len = 0;
    185 
    186     ret = FMR_get_rt(g_idx, &rt, &rt_len);
    187     if (ret) {
    188         LOGE("%s, error, [ret=%d]\n", __func__, ret);
    189         return NULL;
    190     }
    191     LastRadioText = env->NewByteArray(rt_len);
    192     env->SetByteArrayRegion(LastRadioText, 0, rt_len, (const jbyte*)rt);
    193     LOGD("%s, [ret=%d]\n", __func__, ret);
    194     return LastRadioText;
    195 }
    196 
    197 jshort activeAf(JNIEnv *env, jobject thiz)
    198 {
    199     int ret = 0;
    200     jshort ret_freq = 0;
    201 
    202     ret = FMR_active_af(g_idx, (uint16_t*)&ret_freq);
    203     if (ret) {
    204         LOGE("%s, error, [ret=%d]\n", __func__, ret);
    205         return 0;
    206     }
    207     LOGD("%s, [ret=%d]\n", __func__, ret);
    208     return ret_freq;
    209 }
    210 
    211 jshortArray getAFList(JNIEnv *env, jobject thiz)
    212 {
    213     int ret = 0;
    214     jshortArray AFList;
    215     char *af = NULL;
    216     int af_len = 0;
    217 
    218     //ret = FMR_get_af(g_idx, &af, &af_len); // If need, we should implemate this API
    219     if (ret) {
    220         LOGE("%s, error, [ret=%d]\n", __func__, ret);
    221         return NULL;
    222     }
    223     AFList = env->NewShortArray(af_len);
    224     env->SetShortArrayRegion(AFList, 0, af_len, (const jshort*)af);
    225     LOGD("%s, [ret=%d]\n", __func__, ret);
    226     return AFList;
    227 }
    228 
    229 jint setRds(JNIEnv *env, jobject thiz, jboolean rdson)
    230 {
    231     int ret = 0;
    232     int onoff = -1;
    233 
    234     if (rdson == JNI_TRUE) {
    235         onoff = FMR_RDS_ON;
    236     } else {
    237         onoff = FMR_RDS_OFF;
    238     }
    239     ret = FMR_turn_on_off_rds(g_idx, onoff);
    240     if (ret) {
    241         LOGE("%s, error, [ret=%d]\n", __func__, ret);
    242     }
    243     LOGD("%s, [onoff=%d] [ret=%d]\n", __func__, onoff, ret);
    244     return ret?JNI_FALSE:JNI_TRUE;
    245 }
    246 
    247 jboolean stopScan(JNIEnv *env, jobject thiz)
    248 {
    249     int ret = 0;
    250 
    251     ret = FMR_stop_scan(g_idx);
    252     if (ret) {
    253         LOGE("%s, error, [ret=%d]\n", __func__, ret);
    254     }
    255     LOGD("%s, [ret=%d]\n", __func__, ret);
    256     return ret?JNI_FALSE:JNI_TRUE;
    257 }
    258 
    259 jint setMute(JNIEnv *env, jobject thiz, jboolean mute)
    260 {
    261     int ret = 0;
    262 
    263     ret = FMR_set_mute(g_idx, (int)mute);
    264     if (ret) {
    265         LOGE("%s, error, [ret=%d]\n", __func__, ret);
    266     }
    267     LOGD("%s, [mute=%d] [ret=%d]\n", __func__, (int)mute, ret);
    268     return ret?JNI_FALSE:JNI_TRUE;
    269 }
    270 
    271 /******************************************
    272  * Inquiry if RDS is support in driver.
    273  * Parameter:
    274  *      None
    275  *Return Value:
    276  *      1: support
    277  *      0: NOT support
    278  *      -1: error
    279  ******************************************/
    280 jint isRdsSupport(JNIEnv *env, jobject thiz)
    281 {
    282     int ret = 0;
    283     int supt = -1;
    284 
    285     ret = FMR_is_rdsrx_support(g_idx, &supt);
    286     if (ret) {
    287         LOGE("%s, error, [ret=%d]\n", __func__, ret);
    288     }
    289     LOGD("%s, [supt=%d] [ret=%d]\n", __func__, supt, ret);
    290     return supt;
    291 }
    292 
    293 /******************************************
    294  * SwitchAntenna
    295  * Parameter:
    296  *      antenna:
    297                 0 : switch to long antenna
    298                 1: switch to short antenna
    299  *Return Value:
    300  *          0: Success
    301  *          1: Failed
    302  *          2: Not support
    303  ******************************************/
    304 jint switchAntenna(JNIEnv *env, jobject thiz, jint antenna)
    305 {
    306     int ret = 0;
    307     jint jret = 0;
    308     int ana = -1;
    309 
    310     if (0 == antenna) {
    311         ana = FM_LONG_ANA;
    312     } else if (1 == antenna) {
    313         ana = FM_SHORT_ANA;
    314     } else {
    315         LOGE("%s:fail, para error\n", __func__);
    316         jret = JNI_FALSE;
    317         goto out;
    318     }
    319     ret = FMR_ana_switch(g_idx, ana);
    320     if (ret == -ERR_UNSUPT_SHORTANA) {
    321         LOGW("Not support switchAntenna\n");
    322         jret = 2;
    323     } else if (ret) {
    324         LOGE("switchAntenna(), error\n");
    325         jret = 1;
    326     } else {
    327         jret = 0;
    328     }
    329 out:
    330     LOGD("%s: [antenna=%d] [ret=%d]\n", __func__, ana, ret);
    331     return jret;
    332 }
    333 
    334 static const char *classPathNameRx = "com/android/fmradio/FmNative";
    335 
    336 static JNINativeMethod methodsRx[] = {
    337     {"openDev", "()Z", (void*)openDev },  //1
    338     {"closeDev", "()Z", (void*)closeDev }, //2
    339     {"powerUp", "(F)Z", (void*)powerUp },  //3
    340     {"powerDown", "(I)Z", (void*)powerDown }, //4
    341     {"tune", "(F)Z", (void*)tune },          //5
    342     {"seek", "(FZ)F", (void*)seek },         //6
    343     {"autoScan",  "()[S", (void*)autoScan }, //7
    344     {"stopScan",  "()Z", (void*)stopScan },  //8
    345     {"setRds",    "(Z)I", (void*)setRds  },  //10
    346     {"readRds",   "()S", (void*)readRds },  //11 will pending here for get event status
    347     {"getPs",     "()[B", (void*)getPs  },  //12
    348     {"getLrText", "()[B", (void*)getLrText}, //13
    349     {"activeAf",  "()S", (void*)activeAf},   //14
    350     {"setMute",	"(Z)I", (void*)setMute},  //15
    351     {"isRdsSupport",	"()I", (void*)isRdsSupport},  //16
    352     {"switchAntenna", "(I)I", (void*)switchAntenna}, //17
    353 };
    354 
    355 /*
    356  * Register several native methods for one class.
    357  */
    358 static jint registerNativeMethods(JNIEnv* env, const char* className,
    359     JNINativeMethod* gMethods, int numMethods)
    360 {
    361     jclass clazz;
    362 
    363     clazz = env->FindClass(className);
    364     if (env->ExceptionCheck()) {
    365         env->ExceptionDescribe();
    366         env->ExceptionClear();
    367     }
    368     if (clazz == NULL) {
    369         LOGE("Native registration unable to find class '%s'", className);
    370         return JNI_FALSE;
    371     }
    372     if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
    373         LOGE("RegisterNatives failed for '%s'", className);
    374         return JNI_FALSE;
    375     }
    376 
    377     LOGD("%s, success\n", __func__);
    378     return JNI_TRUE;
    379 }
    380 
    381 /*
    382  * Register native methods for all classes we know about.
    383  *
    384  * returns JNI_TRUE on success.
    385  */
    386 static jint registerNatives(JNIEnv* env)
    387 {
    388     jint ret = JNI_FALSE;
    389 
    390     if (registerNativeMethods(env, classPathNameRx,methodsRx,
    391         sizeof(methodsRx) / sizeof(methodsRx[0]))) {
    392         ret = JNI_TRUE;
    393     }
    394 
    395     LOGD("%s, done\n", __func__);
    396     return ret;
    397 }
    398 
    399 // ----------------------------------------------------------------------------
    400 
    401 /*
    402  * This is called by the VM when the shared library is first loaded.
    403  */
    404 
    405 typedef union {
    406     JNIEnv* env;
    407     void* venv;
    408 } UnionJNIEnvToVoid;
    409 
    410 jint JNI_OnLoad(JavaVM* vm, void* reserved)
    411 {
    412     UnionJNIEnvToVoid uenv;
    413     uenv.venv = NULL;
    414     jint result = -1;
    415     JNIEnv* env = NULL;
    416 
    417     LOGI("JNI_OnLoad");
    418 
    419     if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
    420         LOGE("ERROR: GetEnv failed");
    421         goto fail;
    422     }
    423     env = uenv.env;
    424 
    425     if (registerNatives(env) != JNI_TRUE) {
    426         LOGE("ERROR: registerNatives failed");
    427         goto fail;
    428     }
    429 
    430     if ((g_idx = FMR_init()) < 0) {
    431         goto fail;
    432     }
    433     result = JNI_VERSION_1_4;
    434 
    435 fail:
    436     return result;
    437 }
    438 
    439