• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
openDev(JNIEnv * env,jobject thiz)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 
closeDev(JNIEnv * env,jobject thiz)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 
powerUp(JNIEnv * env,jobject thiz,jfloat freq)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 
powerDown(JNIEnv * env,jobject thiz,jint type)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 
tune(JNIEnv * env,jobject thiz,jfloat freq)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 
seek(JNIEnv * env,jobject thiz,jfloat freq,jboolean isUp)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 
autoScan(JNIEnv * env,jobject thiz)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 
readRds(JNIEnv * env,jobject thiz)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 
getPs(JNIEnv * env,jobject thiz)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 
getLrText(JNIEnv * env,jobject thiz)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 
activeAf(JNIEnv * env,jobject thiz)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 
getAFList(JNIEnv * env,jobject thiz)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 
setRds(JNIEnv * env,jobject thiz,jboolean rdson)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 
stopScan(JNIEnv * env,jobject thiz)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 
setMute(JNIEnv * env,jobject thiz,jboolean mute)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  ******************************************/
isRdsSupport(JNIEnv * env,jobject thiz)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  ******************************************/
switchAntenna(JNIEnv * env,jobject thiz,jint antenna)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  */
registerNativeMethods(JNIEnv * env,const char * className,JNINativeMethod * gMethods,int numMethods)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  */
registerNatives(JNIEnv * env)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 
JNI_OnLoad(JavaVM * vm,void * reserved)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