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