blob: 4dcb51a651ff94358d7f70b1cdbf4574752a9c5f [file] [log] [blame]
Venkateshwarlu Domakondaaa253632013-03-25 16:53:03 +05301/*
Ayaz Ahmad05debe62013-09-23 11:50:59 +05302 * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
Venkateshwarlu Domakondaaa253632013-03-25 16:53:03 +05303 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of The Linux Foundation nor
12 * the names of its contributors may be used to endorse or promote
13 * products derived from this software without specific prior written
14 * permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#define LOG_TAG "fmradio"
30
31#include "jni.h"
32#include "JNIHelp.h"
33#include "android_runtime/AndroidRuntime.h"
34#include "utils/Log.h"
35#include "utils/misc.h"
36#include <cutils/properties.h>
37#include <fcntl.h>
38#include <sys/ioctl.h>
39#include <media/tavarua.h>
40#include <linux/videodev2.h>
41#include <math.h>
42
43#define RADIO "/dev/radio0"
44#define FM_JNI_SUCCESS 0L
45#define FM_JNI_FAILURE -1L
46#define SEARCH_DOWN 0
47#define SEARCH_UP 1
48#define TUNE_MULT 16000
49#define HIGH_BAND 2
50#define LOW_BAND 1
51#define CAL_DATA_SIZE 23
52#define V4L2_CTRL_CLASS_USER 0x00980000
53#define V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION (V4L2_CTRL_CLASS_USER + 0x92A)
54#define V4L2_CID_PRIVATE_TAVARUA_ON_CHANNEL_THRESHOLD (V4L2_CTRL_CLASS_USER + 0x92B)
55#define V4L2_CID_PRIVATE_TAVARUA_OFF_CHANNEL_THRESHOLD (V4L2_CTRL_CLASS_USER + 0x92C)
56#define TX_RT_LENGTH 63
57#define WAIT_TIMEOUT 200000 /* 200*1000us */
58#define TX_RT_DELIMITER 0x0d
59#define PS_LEN 9
60#define STD_BUF_SIZE 256
61enum search_dir_t {
62 SEEK_UP,
63 SEEK_DN,
64 SCAN_UP,
65 SCAN_DN
66};
67
68
69using namespace android;
70
71/* native interface */
72static jint android_hardware_fmradio_FmReceiverJNI_acquireFdNative
73 (JNIEnv* env, jobject thiz, jstring path)
74{
75 int fd;
76 int i, retval=0, err;
77 char value[PROPERTY_VALUE_MAX] = {'\0'};
78 char versionStr[40] = {'\0'};
79 int init_success = 0;
80 jboolean isCopy;
81 v4l2_capability cap;
82 const char* radio_path = env->GetStringUTFChars(path, &isCopy);
83 if(radio_path == NULL){
84 return FM_JNI_FAILURE;
85 }
86 fd = open(radio_path, O_RDONLY, O_NONBLOCK);
87 if(isCopy == JNI_TRUE){
88 env->ReleaseStringUTFChars(path, radio_path);
89 }
90 if(fd < 0){
91 return FM_JNI_FAILURE;
92 }
93 //Read the driver verions
94 err = ioctl(fd, VIDIOC_QUERYCAP, &cap);
95
96 ALOGD("VIDIOC_QUERYCAP returns :%d: version: %d \n", err , cap.version );
97
98 if( err >= 0 ) {
99 ALOGD("Driver Version(Same as ChipId): %x \n", cap.version );
100 /*Conver the integer to string */
101 sprintf(versionStr, "%d", cap.version );
102 property_set("hw.fm.version", versionStr);
103 } else {
104 return FM_JNI_FAILURE;
105 }
106 /*Set the mode for soc downloader*/
107 property_set("hw.fm.mode", "normal");
108 /* Need to clear the hw.fm.init firstly */
109 property_set("hw.fm.init", "0");
110 property_set("ctl.start", "fm_dl");
111 sched_yield();
112 for(i=0; i<45; i++) {
113 property_get("hw.fm.init", value, NULL);
114 if (strcmp(value, "1") == 0) {
115 init_success = 1;
116 break;
117 } else {
118 usleep(WAIT_TIMEOUT);
119 }
120 }
121 ALOGE("init_success:%d after %f seconds \n", init_success, 0.2*i);
122 if(!init_success) {
123 property_set("ctl.stop", "fm_dl");
124 // close the fd(power down)
125
126 close(fd);
127 return FM_JNI_FAILURE;
128 }
129 return fd;
130}
131
132/* native interface */
133static jint android_hardware_fmradio_FmReceiverJNI_closeFdNative
134 (JNIEnv * env, jobject thiz, jint fd)
135{
136 int i = 0;
137 int cleanup_success = 0;
138 char value = 0, retval =0;
139
140 property_set("ctl.stop", "fm_dl");
141 close(fd);
142 return FM_JNI_SUCCESS;
143}
144
145/********************************************************************
146 * Current JNI
147 *******************************************************************/
148
149/* native interface */
150static jint android_hardware_fmradio_FmReceiverJNI_getFreqNative
151 (JNIEnv * env, jobject thiz, jint fd)
152{
153 int err;
154 struct v4l2_frequency freq;
155 freq.type = V4L2_TUNER_RADIO;
156 err = ioctl(fd, VIDIOC_G_FREQUENCY, &freq);
157 if(err < 0){
158 return FM_JNI_FAILURE;
159 }
160 return ((freq.frequency*1000)/TUNE_MULT);
161}
162
163/*native interface */
164static jint android_hardware_fmradio_FmReceiverJNI_setFreqNative
165 (JNIEnv * env, jobject thiz, jint fd, jint freq)
166{
167 int err;
168 double tune;
169 struct v4l2_frequency freq_struct;
170 freq_struct.type = V4L2_TUNER_RADIO;
171 freq_struct.frequency = (freq*TUNE_MULT/1000);
172 err = ioctl(fd, VIDIOC_S_FREQUENCY, &freq_struct);
173 if(err < 0){
174 return FM_JNI_FAILURE;
175 }
176 return FM_JNI_SUCCESS;
177}
178
179/* native interface */
180static jint android_hardware_fmradio_FmReceiverJNI_setControlNative
181 (JNIEnv * env, jobject thiz, jint fd, jint id, jint value)
182{
183 struct v4l2_control control;
184 int i;
185 int err;
186 ALOGE("id(%x) value: %x\n", id, value);
187 control.value = value;
188
189 control.id = id;
190 for(i=0;i<3;i++) {
191 err = ioctl(fd,VIDIOC_S_CTRL,&control);
192 if(err >= 0){
193 return FM_JNI_SUCCESS;
194 }
195 }
196 ALOGE("setControl native returned with err %d", err);
197 return FM_JNI_FAILURE;
198}
199
200static jint android_hardware_fmradio_FmReceiverJNI_SetCalibrationNative
201 (JNIEnv * env, jobject thiz, jint fd, jbyteArray buff)
202{
203
204 struct v4l2_ext_control ext_ctl;
205 char tmp[CAL_DATA_SIZE] = {0x00};
206 int err;
207 FILE* cal_file;
208
209 cal_file = fopen("/data/app/Riva_fm_cal", "r" );
210 if(cal_file != NULL) {
211 ext_ctl.id = V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION;
212 if (fread(&tmp[0],1,CAL_DATA_SIZE,cal_file) < CAL_DATA_SIZE)
213 {
214 ALOGE("File read failed");
215 return FM_JNI_FAILURE;
216 }
217 ext_ctl.string = tmp;
218 ext_ctl.size = CAL_DATA_SIZE;
219 struct v4l2_ext_controls v4l2_ctls;
220
221 v4l2_ctls.ctrl_class = V4L2_CTRL_CLASS_USER,
222 v4l2_ctls.count = 1,
223 v4l2_ctls.controls = &ext_ctl;
224 err = ioctl(fd, VIDIOC_S_EXT_CTRLS, &v4l2_ctls );
225 if(err >= 0){
226 return FM_JNI_SUCCESS;
227 }
228 }else {
229 return FM_JNI_SUCCESS;
230 }
231 return FM_JNI_SUCCESS;
232}
233/* native interface */
234static jint android_hardware_fmradio_FmReceiverJNI_getControlNative
235 (JNIEnv * env, jobject thiz, jint fd, jint id)
236{
237 struct v4l2_control control;
238 int err;
239 ALOGE("id(%x)\n", id);
240
241 control.id = id;
242 err = ioctl(fd,VIDIOC_G_CTRL,&control);
243 if(err < 0){
244 return FM_JNI_FAILURE;
245 }
246 return control.value;
247}
248
249/* native interface */
250static jint android_hardware_fmradio_FmReceiverJNI_startSearchNative
251 (JNIEnv * env, jobject thiz, jint fd, jint dir)
252{
253 ALOGE("startSearchNative: Issuing the VIDIOC_S_HW_FREQ_SEEK");
254 struct v4l2_hw_freq_seek hw_seek;
255 int err;
256 hw_seek.seek_upward = dir;
257 hw_seek.type = V4L2_TUNER_RADIO;
258 err = ioctl(fd,VIDIOC_S_HW_FREQ_SEEK,&hw_seek);
259 if(err < 0){
260 ALOGE("startSearchNative: ioctl failed!!! with error %d\n", err);
261 return FM_JNI_FAILURE;
262 } else
263 ALOGE("startSearchNative: ioctl succedded!!!");
264 return FM_JNI_SUCCESS;
265}
266
267/* native interface */
268static jint android_hardware_fmradio_FmReceiverJNI_cancelSearchNative
269 (JNIEnv * env, jobject thiz, jint fd)
270{
271 struct v4l2_control control;
272 int err;
273 control.id=V4L2_CID_PRIVATE_TAVARUA_SRCHON;
274 control.value=0;
275 err = ioctl(fd,VIDIOC_S_CTRL,&control);
276 if(err < 0){
277 return FM_JNI_FAILURE;
278 }
279 return FM_JNI_SUCCESS;
280}
281
282/* native interface */
283static jint android_hardware_fmradio_FmReceiverJNI_getRSSINative
284 (JNIEnv * env, jobject thiz, jint fd)
285{
286 struct v4l2_tuner tuner;
287 int err;
288
289 tuner.index = 0;
290 tuner.signal = 0;
291 err = ioctl(fd, VIDIOC_G_TUNER, &tuner);
292 if(err < 0){
293 return FM_JNI_FAILURE;
294 }
295 return tuner.signal;
296}
297
298/* native interface */
299static jint android_hardware_fmradio_FmReceiverJNI_setBandNative
300 (JNIEnv * env, jobject thiz, jint fd, jint low, jint high)
301{
302 struct v4l2_tuner tuner;
303 int err;
304
305 tuner.index = 0;
306 tuner.signal = 0;
307 tuner.rangelow = low * (TUNE_MULT/1000);
308 tuner.rangehigh = high * (TUNE_MULT/1000);
309 err = ioctl(fd, VIDIOC_S_TUNER, &tuner);
310 if(err < 0){
311 return FM_JNI_FAILURE;
312 }
313 return FM_JNI_SUCCESS;
314}
315
316/* native interface */
317static jint android_hardware_fmradio_FmReceiverJNI_getLowerBandNative
318 (JNIEnv * env, jobject thiz, jint fd)
319{
320 struct v4l2_tuner tuner;
321 int err;
322 tuner.index = 0;
323
324 err = ioctl(fd, VIDIOC_G_TUNER, &tuner);
325 if(err < 0){
326 ALOGE("low_band value: <%x> \n", tuner.rangelow);
327 return FM_JNI_FAILURE;
328 }
329 return ((tuner.rangelow * 1000)/ TUNE_MULT);
330}
331
332/* native interface */
333static jint android_hardware_fmradio_FmReceiverJNI_getUpperBandNative
334 (JNIEnv * env, jobject thiz, jint fd)
335{
336 struct v4l2_tuner tuner;
337 int err;
338 tuner.index = 0;
339
340 err = ioctl(fd, VIDIOC_G_TUNER, &tuner);
341 if(err < 0){
342 ALOGE("high_band value: <%x> \n", tuner.rangehigh);
343 return FM_JNI_FAILURE;
344 }
345 return ((tuner.rangehigh * 1000) / TUNE_MULT);
346}
347
348static jint android_hardware_fmradio_FmReceiverJNI_setMonoStereoNative
349 (JNIEnv * env, jobject thiz, jint fd, jint val)
350{
351
352 struct v4l2_tuner tuner;
353 int err;
354
355 tuner.index = 0;
356 err = ioctl(fd, VIDIOC_G_TUNER, &tuner);
357
358 if(err < 0)
359 return FM_JNI_FAILURE;
360
361 tuner.audmode = val;
362 err = ioctl(fd, VIDIOC_S_TUNER, &tuner);
363
364 if(err < 0)
365 return FM_JNI_FAILURE;
366
367 return FM_JNI_SUCCESS;
368
369}
370
371
372
373/* native interface */
374static jint android_hardware_fmradio_FmReceiverJNI_getBufferNative
375 (JNIEnv * env, jobject thiz, jint fd, jbooleanArray buff, jint index)
376{
377 int err;
378 jboolean isCopy;
379 struct v4l2_requestbuffers reqbuf;
380 struct v4l2_buffer v4l2_buf;
381 memset(&reqbuf, 0, sizeof (reqbuf));
382 enum v4l2_buf_type type = V4L2_BUF_TYPE_PRIVATE;
383 reqbuf.type = V4L2_BUF_TYPE_PRIVATE;
384 reqbuf.memory = V4L2_MEMORY_USERPTR;
385 jboolean *bool_buffer = env->GetBooleanArrayElements(buff,&isCopy);
386 memset(&v4l2_buf, 0, sizeof (v4l2_buf));
387 v4l2_buf.index = index;
388 v4l2_buf.type = type;
389 v4l2_buf.length = STD_BUF_SIZE;
390 v4l2_buf.m.userptr = (unsigned long)bool_buffer;
391 err = ioctl(fd,VIDIOC_DQBUF,&v4l2_buf);
392 if(err < 0){
393 /* free up the memory in failure case*/
394 env->ReleaseBooleanArrayElements(buff, bool_buffer, 0);
395 return FM_JNI_FAILURE;
396 }
397
398 /* Always copy buffer and free up the memory */
399 env->ReleaseBooleanArrayElements(buff, bool_buffer, 0);
400
401 return v4l2_buf.bytesused;
402}
403
404/* native interface */
405static jint android_hardware_fmradio_FmReceiverJNI_getRawRdsNative
406 (JNIEnv * env, jobject thiz, jint fd, jbooleanArray buff, jint count)
407{
408
409 return (read (fd, buff, count));
410
411}
412
413/* native interface */
414static jint android_hardware_fmradio_FmReceiverJNI_setNotchFilterNative(JNIEnv * env, jobject thiz,jint fd, jint id, jboolean aValue)
415{
416 char value[PROPERTY_VALUE_MAX] = {'\0'};
417 int init_success = 0,i;
Ayaz Ahmad05debe62013-09-23 11:50:59 +0530418 char notch[PROPERTY_VALUE_MAX] = {0x00};
Venkateshwarlu Domakondaaa253632013-03-25 16:53:03 +0530419 struct v4l2_control control;
420 int err;
421 /*Enable/Disable the WAN avoidance*/
422 property_set("hw.fm.init", "0");
423 if (aValue)
424 property_set("hw.fm.mode", "wa_enable");
425 else
426 property_set("hw.fm.mode", "wa_disable");
427
428 property_set("ctl.start", "fm_dl");
429 sched_yield();
430 for(i=0; i<10; i++) {
431 property_get("hw.fm.init", value, NULL);
432 if (strcmp(value, "1") == 0) {
433 init_success = 1;
434 break;
435 } else {
436 usleep(WAIT_TIMEOUT);
437 }
438 }
439 ALOGE("init_success:%d after %f seconds \n", init_success, 0.2*i);
440
441 property_get("notch.value", notch, NULL);
442 ALOGE("Notch = %s",notch);
443 if (!strncmp("HIGH",notch,strlen("HIGH")))
444 control.value = HIGH_BAND;
445 else if(!strncmp("LOW",notch,strlen("LOW")))
446 control.value = LOW_BAND;
447 else
448 control.value = 0;
449
450 ALOGE("Notch value : %d", control.value);
451 control.id = id;
452 err = ioctl(fd, VIDIOC_S_CTRL,&control );
453 if(err < 0){
454 return FM_JNI_FAILURE;
455 }
456 return FM_JNI_SUCCESS;
457}
458
459
460/* native interface */
461static jint android_hardware_fmradio_FmReceiverJNI_setAnalogModeNative(JNIEnv * env, jobject thiz, jboolean aValue)
462{
463 int i=0;
464 char value[PROPERTY_VALUE_MAX] = {'\0'};
465 char firmwareVersion[80];
466
467 /*Enable/Disable Analog Mode FM*/
468 property_set("hw.fm.init", "0");
469 if (aValue) {
470 property_set("hw.fm.isAnalog", "true");
471 } else {
472 property_set("hw.fm.isAnalog", "false");
473 }
474 property_set("hw.fm.mode","config_dac");
475 property_set("ctl.start", "fm_dl");
476 sched_yield();
477 for(i=0; i<10; i++) {
478 property_get("hw.fm.init", value, NULL);
479 if (strcmp(value, "1") == 0) {
480 return 1;
481 } else {
482 usleep(WAIT_TIMEOUT);
483 }
484 }
485
486 return 0;
487}
488
489
490
491
492/*
493 * Interfaces added for Tx
494*/
495
496/*native interface */
497static jint android_hardware_fmradio_FmReceiverJNI_setPTYNative
498 (JNIEnv * env, jobject thiz, jint fd, jint pty)
499{
500 ALOGE("->android_hardware_fmradio_FmReceiverJNI_setPTYNative\n");
501 struct v4l2_control control;
502
503 control.id = V4L2_CID_RDS_TX_PTY;
504 control.value = pty & MASK_PTY;
505
506 int err;
507 err = ioctl(fd, VIDIOC_S_CTRL,&control );
508 if(err < 0){
509 return FM_JNI_FAILURE;
510 }
511 return FM_JNI_SUCCESS;
512}
513
514static jint android_hardware_fmradio_FmReceiverJNI_setPINative
515 (JNIEnv * env, jobject thiz, jint fd, jint pi)
516{
517 ALOGE("->android_hardware_fmradio_FmReceiverJNI_setPINative\n");
518
519 struct v4l2_control control;
520
521 control.id = V4L2_CID_RDS_TX_PI;
522 control.value = pi & MASK_PI;
523
524 int err;
525 err = ioctl(fd, VIDIOC_S_CTRL,&control );
526 if(err < 0){
527 ALOGE("->pty native failed");
528 return FM_JNI_FAILURE;
529 }
530
531 return FM_JNI_SUCCESS;
532}
533
534static jint android_hardware_fmradio_FmReceiverJNI_startRTNative
535 (JNIEnv * env, jobject thiz, jint fd, jstring radio_text, jint count )
536{
537 ALOGD("->android_hardware_fmradio_FmReceiverJNI_startRTNative\n");
538
539 struct v4l2_ext_control ext_ctl;
540 struct v4l2_ext_controls v4l2_ctls;
541
542 int err = 0;
543 jboolean isCopy = false;
544 char* rt_string1 = NULL;
545 char* rt_string = (char*)env->GetStringUTFChars(radio_text, &isCopy);
546 if(rt_string == NULL ){
547 ALOGE("RT string is not valid \n");
548 return FM_JNI_FAILURE;
549 }
550
551 rt_string1 = (char*) malloc(TX_RT_LENGTH + 1);
552 if (rt_string1 == NULL) {
553 ALOGE("out of memory \n");
554 env->ReleaseStringUTFChars(radio_text, rt_string);
555 return FM_JNI_FAILURE;
556 }
557 memset (rt_string1, 0, TX_RT_LENGTH + 1);
558 memcpy(rt_string1, rt_string, count);
559
560 if(count < TX_RT_LENGTH)
561 rt_string1[count] = TX_RT_DELIMITER;
562
563 ext_ctl.id = V4L2_CID_RDS_TX_RADIO_TEXT;
564 ext_ctl.string = rt_string1;
565 ext_ctl.size = strlen(rt_string1) + 1;
566
567 /* form the ctrls data struct */
568 v4l2_ctls.ctrl_class = V4L2_CTRL_CLASS_FM_TX,
569 v4l2_ctls.count = 1,
570 v4l2_ctls.controls = &ext_ctl;
571
572
573 err = ioctl(fd, VIDIOC_S_EXT_CTRLS, &v4l2_ctls );
574 env->ReleaseStringUTFChars(radio_text, rt_string);
575 if (rt_string1 != NULL) {
576 free(rt_string1);
577 rt_string1 = NULL;
578 }
579 if(err < 0){
580 ALOGE("VIDIOC_S_EXT_CTRLS for start RT returned : %d\n", err);
581 return FM_JNI_FAILURE;
582 }
583
584 ALOGD("->android_hardware_fmradio_FmReceiverJNI_startRTNative is SUCCESS\n");
585 return FM_JNI_SUCCESS;
586}
587
588static jint android_hardware_fmradio_FmReceiverJNI_stopRTNative
589 (JNIEnv * env, jobject thiz, jint fd )
590{
591 ALOGE("->android_hardware_fmradio_FmReceiverJNI_stopRTNative\n");
592 int err;
593 struct v4l2_control control;
594 control.id = V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_RT;
595
596 err = ioctl(fd, VIDIOC_S_CTRL , &control);
597 if(err < 0){
598 return FM_JNI_FAILURE;
599 }
600 ALOGE("->android_hardware_fmradio_FmReceiverJNI_stopRTNative is SUCCESS\n");
601 return FM_JNI_SUCCESS;
602}
603
604static jint android_hardware_fmradio_FmReceiverJNI_startPSNative
605 (JNIEnv * env, jobject thiz, jint fd, jstring buff, jint count )
606{
607 ALOGD("->android_hardware_fmradio_FmReceiverJNI_startPSNative\n");
608
609 struct v4l2_ext_control ext_ctl;
610 struct v4l2_ext_controls v4l2_ctls;
611 int l;
612 int err = 0;
613 jboolean isCopy = false;
614 char *ps_copy = NULL;
615 const char *ps_string = NULL;
616
617 ps_string = env->GetStringUTFChars(buff, &isCopy);
618 if (ps_string != NULL) {
619 l = strlen(ps_string);
620 if ((l > 0) && ((l + 1) == PS_LEN)) {
621 ps_copy = (char *)malloc(sizeof(char) * PS_LEN);
622 if (ps_copy != NULL) {
623 memset(ps_copy, '\0', PS_LEN);
624 memcpy(ps_copy, ps_string, (PS_LEN - 1));
625 } else {
626 env->ReleaseStringUTFChars(buff, ps_string);
627 return FM_JNI_FAILURE;
628 }
629 } else {
630 env->ReleaseStringUTFChars(buff, ps_string);
631 return FM_JNI_FAILURE;
632 }
633 } else {
634 return FM_JNI_FAILURE;
635 }
636
637 env->ReleaseStringUTFChars(buff, ps_string);
638
639 ext_ctl.id = V4L2_CID_RDS_TX_PS_NAME;
640 ext_ctl.string = ps_copy;
641 ext_ctl.size = PS_LEN;
642
643 /* form the ctrls data struct */
644 v4l2_ctls.ctrl_class = V4L2_CTRL_CLASS_FM_TX,
645 v4l2_ctls.count = 1,
646 v4l2_ctls.controls = &ext_ctl;
647
648 err = ioctl(fd, VIDIOC_S_EXT_CTRLS, &v4l2_ctls);
649 if (err < 0) {
650 ALOGE("VIDIOC_S_EXT_CTRLS for Start PS returned : %d\n", err);
651 free(ps_copy);
652 return FM_JNI_FAILURE;
653 }
654
655 ALOGD("->android_hardware_fmradio_FmReceiverJNI_startPSNative is SUCCESS\n");
656 free(ps_copy);
657
658 return FM_JNI_SUCCESS;
659}
660
661static jint android_hardware_fmradio_FmReceiverJNI_stopPSNative
662 (JNIEnv * env, jobject thiz, jint fd)
663{
664 ALOGE("->android_hardware_fmradio_FmReceiverJNI_stopPSNative\n");
665 struct v4l2_control control;
666 control.id = V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_PS_NAME;
667
668 int err;
669 err = ioctl(fd, VIDIOC_S_CTRL , &control);
670 if(err < 0){
671 return FM_JNI_FAILURE;
672 }
673 ALOGE("->android_hardware_fmradio_FmReceiverJNI_stopPSNative is SUCCESS\n");
674 return FM_JNI_SUCCESS;
675}
676
677static jint android_hardware_fmradio_FmReceiverJNI_configureSpurTable
678 (JNIEnv * env, jobject thiz, jint fd)
679{
680 ALOGD("->android_hardware_fmradio_FmReceiverJNI_configureSpurTable\n");
681 int retval = 0;
682 struct v4l2_control control;
683
684 control.id = V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE;
685 retval = ioctl(fd, VIDIOC_S_CTRL, &control);
686 if (retval < 0) {
687 ALOGE("configureSpurTable: Failed to Write the SPUR Table\n");
688 return FM_JNI_FAILURE;
689 } else
690 ALOGD("configureSpurTable: SPUR Table Configuration successful\n");
691
692 return FM_JNI_SUCCESS;
693}
694
695static jint android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative
696 (JNIEnv * env, jobject thiz, jint fd, jint repCount)
697{
698 ALOGE("->android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative\n");
699
700 struct v4l2_control control;
701
702 control.id = V4L2_CID_PRIVATE_TAVARUA_TX_SETPSREPEATCOUNT;
703 control.value = repCount & MASK_TXREPCOUNT;
704
705 int err;
706 err = ioctl(fd, VIDIOC_S_CTRL,&control );
707 if(err < 0){
708 return FM_JNI_FAILURE;
709 }
710
711 ALOGE("->android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative is SUCCESS\n");
712 return FM_JNI_SUCCESS;
713}
714
715static jint android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative
716 (JNIEnv * env, jobject thiz, jint fd, jint powLevel)
717{
718 ALOGE("->android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative\n");
719
720 struct v4l2_control control;
721
722 control.id = V4L2_CID_TUNE_POWER_LEVEL;
723 control.value = powLevel;
724
725 int err;
726 err = ioctl(fd, VIDIOC_S_CTRL,&control );
727 if(err < 0){
728 return FM_JNI_FAILURE;
729 }
730
731 ALOGE("->android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative is SUCCESS\n");
732 return FM_JNI_SUCCESS;
733}
734
735/*
736 * JNI registration.
737 */
738static JNINativeMethod gMethods[] = {
739 /* name, signature, funcPtr */
740 { "acquireFdNative", "(Ljava/lang/String;)I",
741 (void*)android_hardware_fmradio_FmReceiverJNI_acquireFdNative},
742 { "closeFdNative", "(I)I",
743 (void*)android_hardware_fmradio_FmReceiverJNI_closeFdNative},
744 { "getFreqNative", "(I)I",
745 (void*)android_hardware_fmradio_FmReceiverJNI_getFreqNative},
746 { "setFreqNative", "(II)I",
747 (void*)android_hardware_fmradio_FmReceiverJNI_setFreqNative},
748 { "getControlNative", "(II)I",
749 (void*)android_hardware_fmradio_FmReceiverJNI_getControlNative},
750 { "setControlNative", "(III)I",
751 (void*)android_hardware_fmradio_FmReceiverJNI_setControlNative},
752 { "startSearchNative", "(II)I",
753 (void*)android_hardware_fmradio_FmReceiverJNI_startSearchNative},
754 { "cancelSearchNative", "(I)I",
755 (void*)android_hardware_fmradio_FmReceiverJNI_cancelSearchNative},
756 { "getRSSINative", "(I)I",
757 (void*)android_hardware_fmradio_FmReceiverJNI_getRSSINative},
758 { "setBandNative", "(III)I",
759 (void*)android_hardware_fmradio_FmReceiverJNI_setBandNative},
760 { "getLowerBandNative", "(I)I",
761 (void*)android_hardware_fmradio_FmReceiverJNI_getLowerBandNative},
762 { "getUpperBandNative", "(I)I",
763 (void*)android_hardware_fmradio_FmReceiverJNI_getUpperBandNative},
764 { "getBufferNative", "(I[BI)I",
765 (void*)android_hardware_fmradio_FmReceiverJNI_getBufferNative},
766 { "setMonoStereoNative", "(II)I",
767 (void*)android_hardware_fmradio_FmReceiverJNI_setMonoStereoNative},
768 { "getRawRdsNative", "(I[BI)I",
769 (void*)android_hardware_fmradio_FmReceiverJNI_getRawRdsNative},
770 { "setNotchFilterNative", "(IIZ)I",
771 (void*)android_hardware_fmradio_FmReceiverJNI_setNotchFilterNative},
772 { "startRTNative", "(ILjava/lang/String;I)I",
773 (void*)android_hardware_fmradio_FmReceiverJNI_startRTNative},
774 { "stopRTNative", "(I)I",
775 (void*)android_hardware_fmradio_FmReceiverJNI_stopRTNative},
776 { "startPSNative", "(ILjava/lang/String;I)I",
777 (void*)android_hardware_fmradio_FmReceiverJNI_startPSNative},
778 { "stopPSNative", "(I)I",
779 (void*)android_hardware_fmradio_FmReceiverJNI_stopPSNative},
780 { "setPTYNative", "(II)I",
781 (void*)android_hardware_fmradio_FmReceiverJNI_setPTYNative},
782 { "setPINative", "(II)I",
783 (void*)android_hardware_fmradio_FmReceiverJNI_setPINative},
784 { "setPSRepeatCountNative", "(II)I",
785 (void*)android_hardware_fmradio_FmReceiverJNI_setPSRepeatCountNative},
786 { "setTxPowerLevelNative", "(II)I",
787 (void*)android_hardware_fmradio_FmReceiverJNI_setTxPowerLevelNative},
788 { "setAnalogModeNative", "(Z)I",
789 (void*)android_hardware_fmradio_FmReceiverJNI_setAnalogModeNative},
790 { "SetCalibrationNative", "(I)I",
791 (void*)android_hardware_fmradio_FmReceiverJNI_SetCalibrationNative},
792 { "configureSpurTable", "(I)I",
793 (void*)android_hardware_fmradio_FmReceiverJNI_configureSpurTable},
794
795};
796
797int register_android_hardware_fm_fmradio(JNIEnv* env)
798{
799 return jniRegisterNativeMethods(env, "qcom/fmradio/FmReceiverJNI", gMethods, NELEM(gMethods));
800}
801
802jint JNI_OnLoad(JavaVM *jvm, void *reserved)
803{
804 JNIEnv *e;
805 int status;
806 ALOGE("FM : loading QCOMM FM-JNI\n");
807
808 if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
809 ALOGE("JNI version mismatch error");
810 return JNI_ERR;
811 }
812
813 if ((status = register_android_hardware_fm_fmradio(e)) < 0) {
814 ALOGE("jni adapter service registration failure, status: %d", status);
815 return JNI_ERR;
816 }
817 return JNI_VERSION_1_6;
818}