init
This commit is contained in:
commit
8710a52d67
123 changed files with 20007 additions and 0 deletions
42
libfmjni/Android.bp
Normal file
42
libfmjni/Android.bp
Normal file
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// Copyright (C) 2014 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
cc_library_shared {
|
||||
name: "libfmjni-mediatek",
|
||||
|
||||
stem: "libfmjni",
|
||||
|
||||
overrides: ["libfmjni"],
|
||||
|
||||
srcs: [
|
||||
"fmr_core.cpp",
|
||||
"fmr_err.cpp",
|
||||
"libfm_jni.cpp",
|
||||
"common.cpp",
|
||||
"custom.cpp",
|
||||
],
|
||||
|
||||
header_libs: ["jni_headers"],
|
||||
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"libdl",
|
||||
"liblog",
|
||||
"libmedia",
|
||||
"libnativehelper",
|
||||
],
|
||||
}
|
185
libfmjni/NOTICE
Normal file
185
libfmjni/NOTICE
Normal file
|
@ -0,0 +1,185 @@
|
|||
This MediaTek software package contains software with the following notices and under the following licenses:
|
||||
|
||||
==============================================================================================================
|
||||
|
||||
Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
||||
|
25
libfmjni/README
Normal file
25
libfmjni/README
Normal file
|
@ -0,0 +1,25 @@
|
|||
Libraries of MTK FM feature, including FM power on/off,
|
||||
seek, scan, tune...and some other basic functions.
|
||||
|
||||
WHAT IT DOES?
|
||||
=============
|
||||
Provide FM basic functions
|
||||
|
||||
HOW IT WAS BUILT?
|
||||
==================
|
||||
It needs the following libs from AOSP:
|
||||
1. libcutils
|
||||
2. libdl
|
||||
|
||||
and the following libs from MediaTek:
|
||||
1. libmedia
|
||||
|
||||
HOW TO USE IT?
|
||||
==============
|
||||
Files in this directory is used to
|
||||
generate libraries 'libfmjni'
|
||||
|
||||
These libraries are loaded when system up
|
||||
|
||||
All the source code of this library were written by MediaTek co..
|
||||
|
968
libfmjni/common.cpp
Executable file
968
libfmjni/common.cpp
Executable file
|
@ -0,0 +1,968 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include "fmr.h"
|
||||
|
||||
#ifdef LOG_TAG
|
||||
#undef LOG_TAG
|
||||
#endif
|
||||
#define LOG_TAG "FMLIB_COM"
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
int COM_get_seek_space()
|
||||
{
|
||||
// FM radio seek space, 5:50KHZ; 1:100KHZ; 2:200KHZ
|
||||
if (property_get_int32("persist.vendor.connsys.fm_50khz_support", 0) == 1)
|
||||
return FM_SPACE_50K;
|
||||
return FM_SPACE_DEFAULT;
|
||||
}
|
||||
|
||||
int COM_open_dev(const char *pname, int *fd)
|
||||
{
|
||||
int ret = 0;
|
||||
int tmp = -1;
|
||||
|
||||
FMR_ASSERT(pname);
|
||||
FMR_ASSERT(fd);
|
||||
|
||||
LOGI("COM_open_dev start\n");
|
||||
tmp = open(pname, O_RDWR);
|
||||
if (tmp < 0) {
|
||||
LOGE("Open %s failed, %s\n", pname, strerror(errno));
|
||||
ret = -ERR_INVALID_FD;
|
||||
}
|
||||
*fd = tmp;
|
||||
LOGI("%s, [fd=%d] [ret=%d]\n", __func__, *fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_close_dev(int fd)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
LOGI("COM_close_dev start\n");
|
||||
ret = close(fd);
|
||||
if (ret) {
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_pwr_up(int fd, int band, int freq)
|
||||
{
|
||||
int ret = 0;
|
||||
struct fm_tune_parm parm;
|
||||
|
||||
LOGI("%s, [freq=%d]\n", __func__, freq);
|
||||
bzero(&parm, sizeof(struct fm_tune_parm));
|
||||
|
||||
parm.band = band;
|
||||
parm.freq = freq;
|
||||
parm.hilo = FM_AUTO_HILO_OFF;
|
||||
parm.space = FM_SEEK_SPACE;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_POWERUP, &parm);
|
||||
if (ret) {
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_pwr_down(int fd, int type)
|
||||
{
|
||||
int ret = 0;
|
||||
LOGI("%s, [type=%d]\n", __func__, type);
|
||||
ret = ioctl(fd, FM_IOCTL_POWERDOWN, &type);
|
||||
if (ret) {
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_get_chip_id(int fd, int *chipid)
|
||||
{
|
||||
int ret = 0;
|
||||
uint16_t tmp = 0;
|
||||
|
||||
FMR_ASSERT(chipid);
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_GETCHIPID, &tmp);
|
||||
*chipid = (int)tmp;
|
||||
if (ret){
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [chipid=%x] [ret=%d]\n", __func__, fd, *chipid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_get_rssi(int fd, int *rssi)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
FMR_ASSERT(rssi);
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_GETRSSI, rssi);
|
||||
if(ret){
|
||||
LOGE("%s, failed, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGI("%s, [rssi=%d] [ret=%d]\n", __func__, *rssi, ret);
|
||||
return ret;
|
||||
}
|
||||
/*0x20: space, 0x7E:~*/
|
||||
#define ISVALID(c)((c)>=0x20 && (c)<=0x7E)
|
||||
/*change any char which out of [0x20,0x7E]to space(0x20)*/
|
||||
void COM_change_string(uint8_t *str, int len)
|
||||
{
|
||||
int i = 0;
|
||||
for (i=0; i<len; i++) {
|
||||
if (false == ISVALID(str[i])) {
|
||||
str[i]= 0x20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int COM_get_ps(int fd, RDSData_Struct *rds, uint8_t **ps, int *ps_len)
|
||||
{
|
||||
int ret = 0;
|
||||
char tmp_ps[9] = {0};
|
||||
|
||||
UNUSED(fd);
|
||||
FMR_ASSERT(rds);
|
||||
FMR_ASSERT(ps);
|
||||
FMR_ASSERT(ps_len);
|
||||
|
||||
if (rds->event_status&RDS_EVENT_PROGRAMNAME) {
|
||||
LOGD("%s, Success,[event_status=%d]\n", __func__, rds->event_status);
|
||||
*ps = &rds->PS_Data.PS[3][0];
|
||||
*ps_len = sizeof(rds->PS_Data.PS[3]);
|
||||
|
||||
COM_change_string(*ps, *ps_len);
|
||||
memcpy(tmp_ps, *ps, 8);
|
||||
LOGI("PS=%s\n", tmp_ps);
|
||||
} else {
|
||||
LOGE("%s, Failed,[event_status=%d]\n", __func__, rds->event_status);
|
||||
*ps = NULL;
|
||||
*ps_len = 0;
|
||||
ret = -ERR_RDS_NO_DATA;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_get_rt(int fd, RDSData_Struct *rds, uint8_t **rt, int *rt_len)
|
||||
{
|
||||
int ret = 0;
|
||||
char tmp_rt[65] = { 0 };
|
||||
|
||||
UNUSED(fd);
|
||||
FMR_ASSERT(rds);
|
||||
FMR_ASSERT(rt);
|
||||
FMR_ASSERT(rt_len);
|
||||
|
||||
if (rds->event_status&RDS_EVENT_LAST_RADIOTEXT) {
|
||||
LOGD("%s, Success,[event_status=%d]\n", __func__, rds->event_status);
|
||||
*rt = &rds->RT_Data.TextData[3][0];
|
||||
*rt_len = rds->RT_Data.TextLength;
|
||||
|
||||
COM_change_string(*rt, *rt_len);
|
||||
memcpy(tmp_rt, *rt, 64);
|
||||
LOGI("RT=%s\n", tmp_rt);
|
||||
} else {
|
||||
LOGE("%s, Failed,[event_status=%d]\n", __func__, rds->event_status);
|
||||
*rt = NULL;
|
||||
*rt_len = 0;
|
||||
ret = -ERR_RDS_NO_DATA;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_get_pi(int fd, RDSData_Struct *rds, uint16_t *pi)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
UNUSED(fd);
|
||||
FMR_ASSERT(rds);
|
||||
FMR_ASSERT(pi);
|
||||
|
||||
if (rds->event_status & RDS_EVENT_PI_CODE) {
|
||||
LOGD("%s, Success,[event_status=%d] [PI=%d]\n", __func__, rds->event_status, rds->PI);
|
||||
*pi = rds->PI;
|
||||
} else {
|
||||
LOGI("%s, Failed, there's no pi,[event_status=%d]\n", __func__, rds->event_status);
|
||||
*pi = -1;
|
||||
ret = -ERR_RDS_NO_DATA;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_get_ecc(int fd, RDSData_Struct *rds, uint8_t *ecc)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
UNUSED(fd);
|
||||
FMR_ASSERT(rds);
|
||||
FMR_ASSERT(ecc);
|
||||
|
||||
if (rds->event_status & RDS_EVENT_ECC_CODE) {
|
||||
LOGD("%s, Success,[event_status=%d] [ECC=%d]\n", __func__,
|
||||
rds->event_status, rds->Extend_Country_Code);
|
||||
*ecc = rds->Extend_Country_Code;
|
||||
} else {
|
||||
LOGI("%s, Failed, there's no ECC,[event_status=%d]\n", __func__, rds->event_status);
|
||||
*ecc = -1;
|
||||
ret = -ERR_RDS_NO_DATA;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_get_pty(int fd, RDSData_Struct *rds, uint8_t *pty)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
UNUSED(fd);
|
||||
FMR_ASSERT(rds);
|
||||
FMR_ASSERT(pty);
|
||||
|
||||
if(rds->event_status&RDS_EVENT_PTY_CODE){
|
||||
LOGD("%s, Success,[event_status=%d] [PTY=%d]\n", __func__, rds->event_status, rds->PTY);
|
||||
*pty = rds->PTY;
|
||||
}else{
|
||||
LOGI("%s, Success, there's no pty,[event_status=%d]\n", __func__, rds->event_status);
|
||||
*pty = -1;
|
||||
ret = -ERR_RDS_NO_DATA;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_tune(int fd, int freq, int band)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct fm_tune_parm parm;
|
||||
|
||||
bzero(&parm, sizeof(struct fm_tune_parm));
|
||||
|
||||
parm.band = band;
|
||||
parm.freq = freq;
|
||||
parm.hilo = FM_AUTO_HILO_OFF;
|
||||
parm.space = FM_SEEK_SPACE;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_TUNE, &parm);
|
||||
if (ret) {
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [freq=%d] [ret=%d]\n", __func__, fd, freq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_seek(int fd, int *freq, int band, int dir, int lev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct fm_seek_parm parm;
|
||||
|
||||
bzero(&parm, sizeof(struct fm_tune_parm));
|
||||
|
||||
parm.band = band;
|
||||
parm.freq = *freq;
|
||||
parm.hilo = FM_AUTO_HILO_OFF;
|
||||
parm.space = FM_SEEK_SPACE;
|
||||
if (dir == 1) {
|
||||
parm.seekdir = FM_SEEK_UP;
|
||||
} else if (dir == 0) {
|
||||
parm.seekdir = FM_SEEK_DOWN;
|
||||
}
|
||||
parm.seekth = lev;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_SEEK, &parm);
|
||||
if (ret == 0) {
|
||||
*freq = parm.freq;
|
||||
}
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_set_mute(int fd, int mute)
|
||||
{
|
||||
int ret = 0;
|
||||
int tmp = mute;
|
||||
|
||||
LOGD("%s, start \n", __func__);
|
||||
ret = ioctl(fd, FM_IOCTL_MUTE, &tmp);
|
||||
if (ret) {
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_is_fm_pwrup(int fd, int *pwrup)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_IS_FM_POWERED_UP, pwrup);
|
||||
if (ret) {
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Inquiry if RDS is support in driver.
|
||||
* Parameter:
|
||||
* None
|
||||
*supt Value:
|
||||
* 1: support
|
||||
* 0: NOT support
|
||||
* -1: error
|
||||
******************************************/
|
||||
int COM_is_rdsrx_support(int fd, int *supt)
|
||||
{
|
||||
int ret = 0;
|
||||
int support = -1;
|
||||
|
||||
if (fd < 0) {
|
||||
LOGE("FM isRDSsupport fail, g_fm_fd = %d\n", fd);
|
||||
*supt = -1;
|
||||
ret = -ERR_INVALID_FD;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_RDS_SUPPORT, &support);
|
||||
if (ret) {
|
||||
LOGE("FM FM_IOCTL_RDS_SUPPORT fail, errno = %d\n", errno);
|
||||
//don't support
|
||||
*supt = 0;
|
||||
return ret;
|
||||
}
|
||||
LOGI("isRDSsupport Success,[support=%d]\n", support);
|
||||
*supt = support;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_pre_search(int fd)
|
||||
{
|
||||
fm_s32 ret = 0;
|
||||
ret = ioctl(fd, FM_IOCTL_PRE_SEARCH, 0);
|
||||
LOGD("COM_pre_search:%d\n",ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_restore_search(int fd)
|
||||
{
|
||||
fm_s32 ret = 0;
|
||||
ret = ioctl(fd, FM_IOCTL_RESTORE_SEARCH, 0);
|
||||
LOGD("COM_restore_search:%d\n",ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*soft mute tune function, usually for sw scan implement or CQI log tool*/
|
||||
int COM_Soft_Mute_Tune(int fd, fm_softmute_tune_t *para)
|
||||
{
|
||||
fm_s32 ret = 0;
|
||||
//fm_s32 RSSI = 0, PAMD = 0,MR = 0, ATDC = 0;
|
||||
//fm_u32 PRX = 0;
|
||||
//fm_u16 softmuteGainLvl = 0;
|
||||
fm_softmute_tune_t value;
|
||||
|
||||
value.freq = para->freq;
|
||||
ret = ioctl(fd, FM_IOCTL_SOFT_MUTE_TUNE, &value);
|
||||
if (ret) {
|
||||
LOGE("FM soft mute tune faild:%d\n",ret);
|
||||
return ret;
|
||||
}
|
||||
#if 0
|
||||
LOGD("Raw data of soft mute tune[%d]: RSSI:[%x]PAMD:[%x]MR:[%x]ATDC:[%x]PRX:[%x]SMG:[%x]",para->freq,value.RSSI,value.PAMD,value.MR,value.ATDC,value.PRX,value.SMG);
|
||||
RSSI = ((value.RSSI & 0x03FF) >= 512) ? ((value.RSSI & 0x03FF) - 1024) : (value.RSSI & 0x03FF);
|
||||
PAMD = ((value.PAMD & 0xFF) >= 128) ? ((value.PAMD & 0x00FF) - 256) : (value.PAMD & 0x00FF);
|
||||
MR = ((value.MR & 0x01FF) >= 256) ? ((value.MR & 0x01FF) - 512) : (value.MR & 0x01FF);
|
||||
ATDC =((value.ATDC & 0x0FFF) >= 2048) ? ((value.ATDC & 0x0FFF) - 4096) : (value.ATDC & 0x0FFF);
|
||||
if (ATDC < 0) {
|
||||
ATDC = (~(ATDC)) - 1;//Get abs value of ATDC
|
||||
}
|
||||
PRX = (value.PRX & 0x00FF);
|
||||
softmuteGainLvl = value.SMG;
|
||||
//check if the channel is valid according to each CQIs
|
||||
if ((RSSI >= RSSI_TH)
|
||||
&& (PAMD <= PAMD_TH)
|
||||
&& (ATDC <= ATDC_TH)
|
||||
&& (MR >= MR_TH)
|
||||
&& (PRX >= PRX_TH)
|
||||
&& (softmuteGainLvl <= softMuteGainTH)) {
|
||||
para->valid = fm_true;
|
||||
} else {
|
||||
para->valid = fm_false;
|
||||
}
|
||||
#endif
|
||||
para->valid = value.valid;
|
||||
para->rssi = value.rssi;
|
||||
//LOGI("soft mute tune[%d] valid[%d]: RSSI:[%d]PAMD:[%d]MR:[%d]ATDC:[%d]PRX:[%d]SMG:[%d]",para->freq,para->valid,RSSI,PAMD,MR,ATDC,PRX,softmuteGainLvl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int COM_get_cqi(int fd, int num, char *buf, int buf_len)
|
||||
{
|
||||
int ret;
|
||||
struct fm_cqi_req cqi_req;
|
||||
|
||||
//check buf
|
||||
num = (num > CQI_CH_NUM_MAX) ? CQI_CH_NUM_MAX : num;
|
||||
num = (num < CQI_CH_NUM_MIN) ? CQI_CH_NUM_MIN : num;
|
||||
cqi_req.ch_num = (uint16_t)num;
|
||||
cqi_req.buf_size = cqi_req.ch_num * sizeof(struct fm_cqi);
|
||||
if (!buf || (buf_len < cqi_req.buf_size)) {
|
||||
LOGE("get cqi, invalid buf\n");
|
||||
return -1;
|
||||
}
|
||||
cqi_req.cqi_buf = buf;
|
||||
|
||||
//get cqi from driver
|
||||
ret = ioctl(fd, FM_IOCTL_CQI_GET, &cqi_req);
|
||||
if (ret < 0) {
|
||||
LOGE("get cqi, failed %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int COM_turn_on_off_rds(int fd, int onoff)
|
||||
{
|
||||
int ret = 0;
|
||||
uint16_t rds_on = -1;
|
||||
|
||||
LOGD("Rdsset start\n");
|
||||
if (onoff == FMR_RDS_ON) {
|
||||
rds_on = 1;
|
||||
ret = ioctl(fd, FM_IOCTL_RDS_ONOFF, &rds_on);
|
||||
if (ret) {
|
||||
LOGE("FM_IOCTL_RDS_ON failed\n");
|
||||
return ret;
|
||||
}
|
||||
LOGD("Rdsset Success,[rds_on=%d]\n", rds_on);
|
||||
} else {
|
||||
rds_on = 0;
|
||||
ret = ioctl(fd, FM_IOCTL_RDS_ONOFF, &rds_on);
|
||||
if (ret) {
|
||||
LOGE("FM_IOCTL_RDS_OFF failed\n");
|
||||
return ret;
|
||||
}
|
||||
LOGD("Rdsset Success,[rds_on=%d]\n", rds_on);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_read_rds_data(int fd, RDSData_Struct *rds, uint16_t *rds_status)
|
||||
{
|
||||
int ret = 0;
|
||||
uint16_t event_status;
|
||||
//char tmp_ps[9] = {0};
|
||||
//char tmp_rt[65] = { 0 };
|
||||
|
||||
FMR_ASSERT(rds);
|
||||
FMR_ASSERT(rds_status);
|
||||
|
||||
if (read(fd, rds, sizeof(RDSData_Struct)) == sizeof(RDSData_Struct)) {
|
||||
event_status = rds->event_status;
|
||||
//memcpy(tmp_ps, &rds->PS_Data.PS[3][0], 8);
|
||||
//memcpy(tmp_rt, &rds->RT_Data.TextData[3][0], 64);
|
||||
LOGI("event_status = 0x%x\n", event_status);
|
||||
//memset(tmp_ps, 0, 9);
|
||||
//memset(tmp_rt, 0, 65);
|
||||
*rds_status = event_status;
|
||||
return ret;
|
||||
} else {
|
||||
//LOGE("readrds get no event\n");
|
||||
ret = -ERR_RDS_NO_DATA;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int COM_get_af_pi(int fd, uint16_t *pi)
|
||||
{
|
||||
int ret;
|
||||
struct rds_raw_data rrd;
|
||||
uint16_t pi1, pi2;
|
||||
|
||||
FMR_ASSERT(pi);
|
||||
|
||||
memset(&rrd, 0, sizeof(rrd));
|
||||
ret = ioctl(fd, FM_IOCTL_RDS_GET_LOG, &rrd);
|
||||
if (ret) {
|
||||
LOGE("COM_get_af_pi fail(%d)\n", ret);
|
||||
*pi = 0;
|
||||
return ret;
|
||||
}
|
||||
if (rrd.len == 0) {
|
||||
LOGE("COM_get_af_pi fail, RDS log empty!\n");
|
||||
*pi = 0;
|
||||
return -1;
|
||||
}
|
||||
pi1 = rrd.data[4];
|
||||
pi1 |= (rrd.data[5] << 8);
|
||||
LOGI("data[4]=%02x,data[5]=%02x,pi1=%04x\n", rrd.data[4], rrd.data[5], pi1);
|
||||
pi2 = rrd.data[16];
|
||||
pi2 |= (rrd.data[17] << 8);
|
||||
LOGI("data[16]=%02x,data[17]=%02x,pi2=%04x\n", rrd.data[16], rrd.data[17], pi2);
|
||||
|
||||
if (pi1 == pi2) {
|
||||
LOGI("got af pi!!!\n");
|
||||
*pi = pi1;
|
||||
} else {
|
||||
LOGE("af pi check fail\n");
|
||||
*pi = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int COM_active_af(int fd, RDSData_Struct *rds, CUST_cfg_ds *cfg_data, uint16_t orig_pi, uint16_t cur_freq, uint16_t *ret_freq)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0, j = 0;
|
||||
struct fm_tune_parm parm;
|
||||
struct fm_softmute_tune_t smt_parm;
|
||||
uint16_t set_freq = 0, sw_freq = 0, org_freq = 0;
|
||||
uint16_t PAMD_Value = 0, AF_PAMD_LBound = 0, AF_PAMD_HBound = 0;
|
||||
uint16_t PAMD_Level[25];
|
||||
uint16_t PI[25];
|
||||
uint16_t PAMD_DB_TBL[5] = {// 5dB, 10dB, 15dB, 20dB, 25dB,
|
||||
// 13, 17, 21, 25, 29};
|
||||
8, 12, 15, 18, 20};
|
||||
AF_Info af_list_backup;
|
||||
AF_Info af_list;
|
||||
FMR_ASSERT(rds);
|
||||
FMR_ASSERT(cfg_data);
|
||||
sw_freq = cur_freq; //current freq
|
||||
org_freq = cur_freq;
|
||||
parm.band = cfg_data->band;
|
||||
parm.freq = sw_freq;
|
||||
parm.hilo = FM_AUTO_HILO_OFF;
|
||||
parm.space = FM_SPACE_DEFAULT;
|
||||
|
||||
if (!(rds->event_status & RDS_EVENT_AF)) {
|
||||
LOGE("activeAF failed\n");
|
||||
*ret_freq = 0;
|
||||
ret = -ERR_RDS_NO_DATA;
|
||||
return ret;
|
||||
}
|
||||
memset(&af_list_backup, 0, sizeof(af_list_backup));
|
||||
memcpy(&af_list_backup, &rds->AF_Data, sizeof(AF_Info));
|
||||
memset(&af_list, 0, sizeof(af_list));
|
||||
|
||||
AF_PAMD_LBound = PAMD_DB_TBL[0]; //5dB
|
||||
AF_PAMD_HBound = PAMD_DB_TBL[1]; //15dB
|
||||
ioctl(fd, FM_IOCTL_GETCURPAMD, &PAMD_Value);
|
||||
for (i = 0; i < 3 && (PAMD_Value < AF_PAMD_LBound); i++) {
|
||||
usleep(10 * 1000);
|
||||
ioctl(fd, FM_IOCTL_GETCURPAMD, &PAMD_Value);
|
||||
LOGI("check PAMD %d time(s), PAMD =%d", i+1, PAMD_Value);
|
||||
}
|
||||
LOGI("current_freq=%d, PAMD_Value=%d, orig_pi=%d\n", cur_freq, PAMD_Value, orig_pi);
|
||||
|
||||
/* Start to detect AF channels when orignal channel turn weak */
|
||||
if (PAMD_Value < AF_PAMD_LBound) {
|
||||
|
||||
/* Make sure rds->AF_Data.AF_Num is valid */
|
||||
af_list_backup.AF_Num = af_list_backup.AF_Num > 25 ? 25 : af_list_backup.AF_Num;
|
||||
|
||||
/* Precheck af list*/
|
||||
for (i = 0, j = 0; i < af_list_backup.AF_Num; i++) {
|
||||
set_freq = af_list_backup.AF[1][i];
|
||||
if(set_freq < cfg_data->low_band || set_freq > cfg_data->high_band) {
|
||||
/*band check fail*/
|
||||
LOGI("AF[1][%d]:freq %d out of bandwidth[%d,%d], skip!\n",
|
||||
i, af_list_backup.AF[1][i], cfg_data->low_band, cfg_data->high_band);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Using Com_Soft_Mute_Tune to query valid channel*/
|
||||
memset(&smt_parm, 0, sizeof(fm_softmute_tune_t));
|
||||
smt_parm.freq = set_freq;
|
||||
COM_Soft_Mute_Tune(fd, &smt_parm);
|
||||
LOGE("af list pre-check:freq %d, valid:%d\n", smt_parm.freq, smt_parm.valid);
|
||||
if(smt_parm.valid == 1) {
|
||||
/* Update valid AF channel to af_list*/
|
||||
af_list.AF[1][j] = af_list_backup.AF[1][i];
|
||||
j++;
|
||||
af_list.AF_Num++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*AF switch process*/
|
||||
for (i = 0; i < af_list.AF_Num; i++) {
|
||||
set_freq = af_list.AF[1][i];
|
||||
LOGI("set_freq[%d] = %d, org_freq = %d\n", i, set_freq, org_freq);
|
||||
|
||||
if (set_freq != org_freq) {
|
||||
// Set mute to check every af channels
|
||||
COM_set_mute(fd, 1);
|
||||
parm.freq = set_freq;
|
||||
ioctl(fd, FM_IOCTL_TUNE, &parm);
|
||||
usleep(20 * 1000);
|
||||
ioctl(fd, FM_IOCTL_GETCURPAMD, &PAMD_Level[i]);
|
||||
|
||||
/* If signal is not good enough, skip */
|
||||
if (PAMD_Level[i] < AF_PAMD_HBound) {
|
||||
LOGI("PAMD_Level[%d] =%d < AF_PAMD_HBound, continue", i, PAMD_Level[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0 ; j < 5; j++ ) {
|
||||
usleep(200 * 1000);
|
||||
/* Query pi to 5 times */
|
||||
if (COM_get_af_pi(fd, &PI[i])) {
|
||||
if (j == 4)
|
||||
LOGE("get af pi fail\n");
|
||||
continue;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
if (orig_pi != PI[i]) {
|
||||
LOGI("pi not match, current pi(%04x), orig pi(%04x)\n", PI[i], orig_pi);
|
||||
continue;
|
||||
}
|
||||
LOGI("next_freq=%d, PAMD_Level[%d]=%d\n", parm.freq, i, PAMD_Level[i]);
|
||||
/* To get largest PAMD */
|
||||
/* This is a trade-off*/
|
||||
/* If want to get a better quality AF channel, do as follows, it will spend longer to do AF switch*/
|
||||
/* If want to mute shorter, just use one fixed PAMD_VALUE, don't need to compare */
|
||||
if (PAMD_Level[i] > AF_PAMD_HBound) {
|
||||
LOGI("PAMD_Level[%d] =%d > AF_PAMD_HBound, af switch", i, PAMD_Level[i]);
|
||||
sw_freq = set_freq;
|
||||
PAMD_Value = PAMD_Level[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGI("AF deside tune to freq: %d, PAMD_Level: %d\n", sw_freq, PAMD_Value);
|
||||
if ((PAMD_Value > AF_PAMD_HBound)&&(sw_freq != 0)) { /* Tune to AF channel */
|
||||
parm.freq = sw_freq;
|
||||
ioctl(fd, FM_IOCTL_TUNE, &parm);
|
||||
cur_freq = parm.freq;
|
||||
} else { /* Tune to orignal channel */
|
||||
parm.freq = org_freq;
|
||||
ioctl(fd, FM_IOCTL_TUNE, &parm);
|
||||
cur_freq = parm.freq;
|
||||
}
|
||||
/* Unmute when finish AF switch */
|
||||
COM_set_mute(fd, 0);
|
||||
} else {
|
||||
LOGD("RDS_EVENT_AF old freq:%d\n", org_freq);
|
||||
}
|
||||
*ret_freq = cur_freq;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_active_ta(int fd, RDSData_Struct *rds, int band, uint16_t cur_freq, uint16_t *backup_freq, uint16_t *ret_freq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
FMR_ASSERT(rds);
|
||||
FMR_ASSERT(backup_freq);
|
||||
FMR_ASSERT(ret_freq);
|
||||
|
||||
if(rds->event_status&RDS_EVENT_TAON){
|
||||
uint16_t rds_on = 0;
|
||||
struct fm_tune_parm parm;
|
||||
uint16_t PAMD_Level[25];
|
||||
uint16_t PAMD_DB_TBL[5] = {13, 17, 21, 25, 29};
|
||||
uint16_t set_freq, sw_freq, org_freq, PAMD_Value, TA_PAMD_Threshold;
|
||||
int i = 0;
|
||||
|
||||
rds_on = 0;
|
||||
ioctl(fd, FM_IOCTL_RDS_ONOFF, &rds_on);
|
||||
TA_PAMD_Threshold = PAMD_DB_TBL[2]; //15dB
|
||||
sw_freq = cur_freq;
|
||||
org_freq = cur_freq;
|
||||
*backup_freq = org_freq;
|
||||
parm.band = band;
|
||||
parm.freq = sw_freq;
|
||||
parm.hilo = FM_AUTO_HILO_OFF;
|
||||
parm.space = COM_get_seek_space();
|
||||
|
||||
ioctl(fd, FM_IOCTL_GETCURPAMD, &PAMD_Value);
|
||||
//make sure rds->AF_Data.AF_Num is valid
|
||||
rds->AFON_Data.AF_Num = (rds->AFON_Data.AF_Num > 25)? 25 : rds->AFON_Data.AF_Num;
|
||||
for(i=0; i< rds->AFON_Data.AF_Num; i++){
|
||||
set_freq = rds->AFON_Data.AF[1][i];
|
||||
LOGI("set_freq=0x%02x,org_freq=0x%02x\n", set_freq, org_freq);
|
||||
if(set_freq != org_freq){
|
||||
parm.freq = sw_freq;
|
||||
ioctl(fd, FM_IOCTL_TUNE, &parm);
|
||||
ioctl(fd, FM_IOCTL_GETCURPAMD, &PAMD_Level[i]);
|
||||
if(PAMD_Level[i] > PAMD_Value){
|
||||
PAMD_Value = PAMD_Level[i];
|
||||
sw_freq = set_freq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((PAMD_Value > TA_PAMD_Threshold)&&(sw_freq != 0)){
|
||||
rds->Switch_TP= 1;
|
||||
parm.freq = sw_freq;
|
||||
ioctl(fd, FM_IOCTL_TUNE, &parm);
|
||||
cur_freq = parm.freq;
|
||||
}else{
|
||||
parm.freq = org_freq;
|
||||
ioctl(fd, FM_IOCTL_TUNE, &parm);
|
||||
cur_freq = parm.freq;
|
||||
}
|
||||
rds_on = 1;
|
||||
ioctl(fd, FM_IOCTL_RDS_ONOFF, &rds_on);
|
||||
}
|
||||
|
||||
*ret_freq = cur_freq;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_deactive_ta(int fd, RDSData_Struct *rds, int band, uint16_t cur_freq, uint16_t *backup_freq, uint16_t *ret_freq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
UNUSED(band);
|
||||
FMR_ASSERT(rds);
|
||||
FMR_ASSERT(backup_freq);
|
||||
FMR_ASSERT(ret_freq);
|
||||
|
||||
if(rds->event_status&RDS_EVENT_TAON_OFF){
|
||||
uint16_t rds_on = 0;
|
||||
struct fm_tune_parm parm;
|
||||
parm.band = FM_RAIDO_BAND;
|
||||
parm.freq = *backup_freq;
|
||||
parm.hilo = FM_AUTO_HILO_OFF;
|
||||
parm.space = COM_get_seek_space();
|
||||
|
||||
ioctl(fd, FM_IOCTL_RDS_ONOFF, &rds_on);
|
||||
|
||||
ioctl(fd, FM_IOCTL_TUNE, &parm);
|
||||
cur_freq = parm.freq;
|
||||
rds_on = 1;
|
||||
ioctl(fd, FM_IOCTL_RDS_ONOFF, &rds_on);
|
||||
}
|
||||
|
||||
*ret_freq = cur_freq;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_ana_switch(int fd, int antenna)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_ANA_SWITCH, &antenna);
|
||||
if (ret < 0) {
|
||||
LOGE("%s: fail, ret = %d\n", __func__, ret);
|
||||
}
|
||||
|
||||
LOGD("%s: [ret = %d]\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_get_badratio(int fd, int *badratio)
|
||||
{
|
||||
int ret = 0;
|
||||
uint16_t tmp = 0;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_GETBLERRATIO, &tmp);
|
||||
*badratio = (int)tmp;
|
||||
if (ret){
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int COM_get_stereomono(int fd, int *stemono)
|
||||
{
|
||||
int ret = 0;
|
||||
uint16_t tmp = 0;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_GETMONOSTERO, &tmp);
|
||||
*stemono = (int)tmp;
|
||||
if (ret){
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_set_stereomono(int fd, int stemono)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_SETMONOSTERO, &stemono);
|
||||
if (ret){
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_get_caparray(int fd, int *caparray)
|
||||
{
|
||||
int ret = 0;
|
||||
int tmp = 0;
|
||||
|
||||
LOGD("%s, [fd=%d]\n", __func__, fd);
|
||||
ret = ioctl(fd, FM_IOCTL_GETCAPARRAY, &tmp);
|
||||
if (ret){
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
*caparray = tmp;
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int COM_get_hw_info(int fd, struct fm_hw_info *info)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_GET_HW_INFO, info);
|
||||
if(ret){
|
||||
LOGE("%s, failed\n", __func__);
|
||||
}
|
||||
LOGD("%s, [fd=%d] [ret=%d]\n", __func__, fd, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* COM_is_dese_chan -- check if gived channel is a de-sense channel or not
|
||||
* @fd - fd of "dev/fm"
|
||||
* @freq - gived channel
|
||||
* return value: 0, not a dese chan; 1, a dese chan; else error NO.
|
||||
*/
|
||||
int COM_is_dese_chan(int fd, int freq)
|
||||
{
|
||||
int ret = 0;
|
||||
int tmp = freq;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_IS_DESE_CHAN, &freq);
|
||||
if (ret < 0) {
|
||||
LOGE("%s, failed,ret=%d\n", __func__,ret);
|
||||
return ret;
|
||||
} else {
|
||||
LOGD("[fd=%d] %d --> dese=%d\n", fd, tmp, freq);
|
||||
return freq;
|
||||
}
|
||||
}
|
||||
|
||||
/* COM_desense_check -- check if gived channel is a de-sense channel or not
|
||||
* @fd - fd of "dev/fm"
|
||||
* @freq - gived channel
|
||||
* @rssi-freq's rssi
|
||||
* return value: 0, is desense channel and rssi is less than threshold; 1, not desense channel or it is but rssi is more than threshold.
|
||||
*/
|
||||
int COM_desense_check(int fd, int freq, int rssi)
|
||||
{
|
||||
int ret = 0;
|
||||
fm_desense_check_t parm;
|
||||
|
||||
parm.freq = freq;
|
||||
parm.rssi = rssi;
|
||||
ret = ioctl(fd, FM_IOCTL_DESENSE_CHECK, &parm);
|
||||
if (ret < 0) {
|
||||
LOGE("%s, failed,ret=%d\n", __func__,ret);
|
||||
return ret;
|
||||
} else {
|
||||
LOGD("[fd=%d] %d --> dese=%d\n", fd,freq,ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/*
|
||||
th_idx:
|
||||
threshold type: 0, RSSI. 1,desense RSSI. 2,SMG.
|
||||
th_val: threshold value*/
|
||||
int COM_set_search_threshold(int fd, int th_idx,int th_val)
|
||||
{
|
||||
int ret = 0;
|
||||
fm_search_threshold_t th_parm;
|
||||
th_parm.th_type = th_idx;
|
||||
th_parm.th_val = th_val;
|
||||
ret = ioctl(fd, FM_IOCTL_SET_SEARCH_THRESHOLD, &th_parm);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOGE("%s, failed,ret=%d\n", __func__,ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int COM_full_cqi_logger(int fd, fm_full_cqi_log_t *log_parm)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = ioctl(fd, FM_IOCTL_FULL_CQI_LOG, log_parm);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOGE("%s, failed,ret=%d\n", __func__,ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
void FM_interface_init(struct fm_cbk_tbl *cbk_tbl)
|
||||
{
|
||||
//Basic functions.
|
||||
cbk_tbl->open_dev = COM_open_dev;
|
||||
cbk_tbl->close_dev = COM_close_dev;
|
||||
cbk_tbl->pwr_up = COM_pwr_up;
|
||||
cbk_tbl->pwr_down = COM_pwr_down;
|
||||
cbk_tbl->tune = COM_tune;
|
||||
cbk_tbl->set_mute = COM_set_mute;
|
||||
cbk_tbl->is_rdsrx_support = COM_is_rdsrx_support;
|
||||
cbk_tbl->turn_on_off_rds = COM_turn_on_off_rds;
|
||||
cbk_tbl->get_chip_id = COM_get_chip_id;
|
||||
//For RDS RX.
|
||||
cbk_tbl->read_rds_data = COM_read_rds_data;
|
||||
cbk_tbl->get_pi = COM_get_pi;
|
||||
cbk_tbl->get_ps = COM_get_ps;
|
||||
cbk_tbl->get_ecc = COM_get_ecc;
|
||||
cbk_tbl->get_pty = COM_get_pty;
|
||||
cbk_tbl->get_rssi = COM_get_rssi;
|
||||
cbk_tbl->get_rt = COM_get_rt;
|
||||
cbk_tbl->active_af = COM_active_af;
|
||||
cbk_tbl->active_ta = COM_active_ta;
|
||||
cbk_tbl->deactive_ta = COM_deactive_ta;
|
||||
//FM short antenna
|
||||
cbk_tbl->ana_switch = COM_ana_switch;
|
||||
cbk_tbl->desense_check = COM_desense_check;
|
||||
//RX EM mode use
|
||||
cbk_tbl->get_badratio = COM_get_badratio;
|
||||
cbk_tbl->get_stereomono = COM_get_stereomono;
|
||||
cbk_tbl->set_stereomono = COM_set_stereomono;
|
||||
cbk_tbl->get_caparray = COM_get_caparray;
|
||||
cbk_tbl->get_cqi = COM_get_cqi;
|
||||
cbk_tbl->is_dese_chan = COM_is_dese_chan;
|
||||
cbk_tbl->desense_check = COM_desense_check;
|
||||
cbk_tbl->get_hw_info = COM_get_hw_info;
|
||||
//soft mute tune
|
||||
cbk_tbl->soft_mute_tune = COM_Soft_Mute_Tune;
|
||||
cbk_tbl->pre_search = COM_pre_search;
|
||||
cbk_tbl->restore_search = COM_restore_search;
|
||||
//EM
|
||||
cbk_tbl->set_search_threshold = COM_set_search_threshold;
|
||||
cbk_tbl->full_cqi_logger = COM_full_cqi_logger;
|
||||
return;
|
||||
}
|
||||
|
263
libfmjni/custom.cpp
Normal file
263
libfmjni/custom.cpp
Normal file
|
@ -0,0 +1,263 @@
|
|||
/* Copyright Statement:
|
||||
*
|
||||
* This software/firmware and related documentation ("MediaTek Software") are
|
||||
* protected under relevant copyright laws. The information contained herein is
|
||||
* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
|
||||
* the prior written permission of MediaTek inc. and/or its licensors, any
|
||||
* reproduction, modification, use or disclosure of MediaTek Software, and
|
||||
* information contained herein, in whole or in part, shall be strictly
|
||||
* prohibited.
|
||||
*
|
||||
* MediaTek Inc. (C) 2010. All rights reserved.
|
||||
*
|
||||
* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
|
||||
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
|
||||
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
|
||||
* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
|
||||
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||
* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
|
||||
* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
|
||||
* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
|
||||
* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
|
||||
* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
|
||||
* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
|
||||
* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
|
||||
* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
|
||||
* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
|
||||
* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
|
||||
* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
|
||||
* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
|
||||
* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
|
||||
*
|
||||
* The following software/firmware and/or related documentation ("MediaTek
|
||||
* Software") have been modified by MediaTek Inc. All revisions are subject to
|
||||
* any receiver's applicable license agreements with MediaTek Inc.
|
||||
*/
|
||||
|
||||
#define MTK_LOG_ENABLE 1
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "fmr.h"
|
||||
#include "fmlib_cust.h"
|
||||
|
||||
#undef LOGV
|
||||
#define LOGV(...) ALOGV(__VA_ARGS__)
|
||||
#undef LOGD
|
||||
#define LOGD(...) ALOGD(__VA_ARGS__)
|
||||
#undef LOGI
|
||||
#define LOGI(...) ALOGI(__VA_ARGS__)
|
||||
#undef LOGW
|
||||
#define LOGW(...) ALOGW(__VA_ARGS__)
|
||||
#undef LOGE
|
||||
#define LOGE(...) ALOGE(__VA_ARGS__)
|
||||
#ifdef LOG_TAG
|
||||
#undef LOG_TAG
|
||||
#endif
|
||||
#define LOG_TAG "FMLIB_CUST"
|
||||
|
||||
#define MT6620_FM_FAKE_CHANNEL \
|
||||
{ \
|
||||
{10400, -40, -1}, \
|
||||
{9100, -40, -1}, \
|
||||
{9600, -40, -1}, \
|
||||
{9220, -80, -1}, \
|
||||
{0, 0, 0} \
|
||||
}
|
||||
|
||||
#define MT6628_FM_FAKE_CHANNEL \
|
||||
{ \
|
||||
{0, 0, 0} \
|
||||
}
|
||||
|
||||
#define MT6627_FM_FAKE_CHANNEL \
|
||||
{ \
|
||||
{9600, -107, -1}, \
|
||||
{10400, -107, -1}, \
|
||||
{10750, -224, -1}, \
|
||||
{0, 0, 0} \
|
||||
}
|
||||
#define MT6580_FM_FAKE_CHANNEL \
|
||||
{ \
|
||||
{9600, -107, -1}, \
|
||||
{9570, -258, -1}, \
|
||||
{9580, -258, -1}, \
|
||||
{9590, -258, -1}, \
|
||||
{10400, -107, -1}, \
|
||||
{0, 0, 0} \
|
||||
}
|
||||
|
||||
#define MT6630_FM_FAKE_CHANNEL \
|
||||
{ \
|
||||
{9600,-107,-1}, \
|
||||
{10400,-107,-1}, \
|
||||
{0, 0, 0} \
|
||||
}
|
||||
|
||||
#define MT6631_FM_FAKE_CHANNEL \
|
||||
{ \
|
||||
{9210, -205, -1}, \
|
||||
{9600, -152, -1}, \
|
||||
{10400, -152, -1}, \
|
||||
{10750, -205, -1}, \
|
||||
{0, 0, 0} \
|
||||
}
|
||||
|
||||
#define MT6632_FM_FAKE_CHANNEL \
|
||||
{ \
|
||||
{9600, -107, -1}, \
|
||||
{10400, -107, -1}, \
|
||||
{0, 0, 0} \
|
||||
}
|
||||
|
||||
static struct fm_fake_channel mt6620_fake_ch[] = MT6620_FM_FAKE_CHANNEL;
|
||||
static struct fm_fake_channel mt6627_fake_ch[] = MT6627_FM_FAKE_CHANNEL;
|
||||
static struct fm_fake_channel mt6628_fake_ch[] = MT6628_FM_FAKE_CHANNEL;
|
||||
static struct fm_fake_channel mt6580_fake_ch[] = MT6580_FM_FAKE_CHANNEL;
|
||||
static struct fm_fake_channel mt6630_fake_ch[] = MT6630_FM_FAKE_CHANNEL;
|
||||
static struct fm_fake_channel mt6631_fake_ch[] = MT6631_FM_FAKE_CHANNEL;
|
||||
static struct fm_fake_channel mt6632_fake_ch[] = MT6632_FM_FAKE_CHANNEL;
|
||||
|
||||
static struct fm_fake_channel_t fake_ch_info = {0, 0};
|
||||
|
||||
void CUST_update_cfg(struct CUST_cfg_ds *cfg, int chipid)
|
||||
{
|
||||
struct fm_fake_channel *fake_ch = NULL;
|
||||
|
||||
LOGI("update connsys chipid=0x%x\n", chipid);
|
||||
|
||||
switch (chipid)
|
||||
{
|
||||
case FM_CHIP_MT6580:
|
||||
cfg->chip = FM_CHIP_MT6580;
|
||||
fake_ch = mt6580_fake_ch;
|
||||
break;
|
||||
case FM_CHIP_MT6620:
|
||||
cfg->chip = FM_CHIP_MT6620;
|
||||
fake_ch = mt6620_fake_ch;
|
||||
break;
|
||||
case FM_CHIP_MT6627:
|
||||
cfg->chip = FM_CHIP_MT6627;
|
||||
fake_ch = mt6627_fake_ch;
|
||||
break;
|
||||
case FM_CHIP_MT6628:
|
||||
cfg->chip = FM_CHIP_MT6628;
|
||||
fake_ch = mt6628_fake_ch;
|
||||
break;
|
||||
case FM_CHIP_MT6630:
|
||||
cfg->chip = FM_CHIP_MT6630;
|
||||
fake_ch = mt6630_fake_ch;
|
||||
break;
|
||||
case FM_CHIP_MT6631:
|
||||
cfg->chip = FM_CHIP_MT6631;
|
||||
fake_ch = mt6631_fake_ch;
|
||||
break;
|
||||
case FM_CHIP_MT6632:
|
||||
cfg->chip = FM_CHIP_MT6632;
|
||||
fake_ch = mt6632_fake_ch;
|
||||
break;
|
||||
case FM_CHIP_MT6635:
|
||||
cfg->chip = FM_CHIP_MT6635;
|
||||
fake_ch = mt6631_fake_ch;
|
||||
break;
|
||||
default:
|
||||
LOGE("not support chipid=0x%x\n", chipid);
|
||||
break;
|
||||
}
|
||||
|
||||
cfg->band = FM_RAIDO_BAND; // 1, UE; 2, JAPAN; 3, JAPANW
|
||||
|
||||
cfg->low_band = FM_FREQ_MIN * 10;
|
||||
cfg->high_band = FM_FREQ_MAX * 10;
|
||||
|
||||
if (property_get_int32("persist.vendor.connsys.fm_50khz_support", 0) == 1) {
|
||||
cfg->seek_space = 5; // FM radio seek space, 5:50KHZ; 1:100KHZ; 2:200KHZ
|
||||
} else {
|
||||
cfg->seek_space = 1;
|
||||
}
|
||||
|
||||
cfg->max_scan_num = FM_MAX_CHL_SIZE;
|
||||
cfg->seek_lev = FM_SEEKTH_LEVEL_DEFAULT;
|
||||
cfg->scan_sort = FM_SCAN_SORT_SELECT;
|
||||
|
||||
if (property_get_int32("persist.vendor.connsys.fm_short_antenna_support", 0) == 1) {
|
||||
cfg->short_ana_sup = fm_false;
|
||||
} else {
|
||||
cfg->short_ana_sup = fm_true;
|
||||
}
|
||||
|
||||
cfg->rssi_th_l2 = FM_CHIP_DESE_RSSI_TH;
|
||||
cfg->rssi_th_l2 = (cfg->rssi_th_l2 > -72) ? -72 : cfg->rssi_th_l2;
|
||||
cfg->rssi_th_l2 = (cfg->rssi_th_l2 < -102) ? -102 : cfg->rssi_th_l2;
|
||||
|
||||
if (fake_ch) {
|
||||
fake_ch_info.chan = fake_ch;
|
||||
fake_ch_info.size = 0;
|
||||
while (fake_ch[fake_ch_info.size].freq > 0) {
|
||||
fake_ch_info.size++;
|
||||
}
|
||||
}
|
||||
|
||||
cfg->fake_chan = &fake_ch_info;
|
||||
}
|
||||
|
||||
int CUST_get_cfg(struct CUST_cfg_ds *cfg)
|
||||
{
|
||||
char val[PROPERTY_VALUE_MAX] = {0};
|
||||
int chipid = FM_CHIP_UNSUPPORTED;
|
||||
|
||||
if (property_get("persist.vendor.connsys.fm_chipid", val, NULL)) {
|
||||
if (strcmp(val, "soc") == 0) {
|
||||
chipid = FM_CHIP_MT6580;
|
||||
} else if (strcmp(val, "mt6620") == 0) {
|
||||
chipid = FM_CHIP_MT6620;
|
||||
} else if (strcmp(val, "mt6627") == 0) {
|
||||
chipid = FM_CHIP_MT6627;
|
||||
} else if (strcmp(val, "mt6628") == 0) {
|
||||
chipid = FM_CHIP_MT6628;
|
||||
} else if (strcmp(val, "mt6630") == 0) {
|
||||
chipid = FM_CHIP_MT6630;
|
||||
} else if (strcmp(val, "mt6631") == 0) {
|
||||
chipid = FM_CHIP_MT6631;
|
||||
} else if (strcmp(val, "mt6632") == 0) {
|
||||
chipid = FM_CHIP_MT6632;
|
||||
} else if ((strcmp(val, "mt6635") == 0)
|
||||
|| (strcmp(val, "connac2x") == 0)) {
|
||||
chipid = FM_CHIP_MT6635;
|
||||
}
|
||||
}
|
||||
|
||||
if (chipid == FM_CHIP_UNSUPPORTED) {
|
||||
if (property_get("vendor.connsys.fm.adie.chipid", val, NULL)) {
|
||||
if (strcmp(val, "0x6631") == 0) {
|
||||
chipid = FM_CHIP_MT6631;
|
||||
} else if ((strcmp(val, "0x6635") == 0)
|
||||
|| (strcmp(val, "0x6637") == 0)) {
|
||||
chipid = FM_CHIP_MT6635;
|
||||
} else {
|
||||
LOGE("not support chipid=%s\n", val);
|
||||
}
|
||||
} else if (property_get("vendor.connsys.adie.chipid", val, NULL)) {
|
||||
if (strcmp(val, "0x6631") == 0) {
|
||||
chipid = FM_CHIP_MT6631;
|
||||
} else if ((strcmp(val, "0x6635") == 0)
|
||||
|| (strcmp(val, "0x6637") == 0)) {
|
||||
chipid = FM_CHIP_MT6635;
|
||||
} else {
|
||||
LOGE("not support chipid=%s\n", val);
|
||||
}
|
||||
} else {
|
||||
LOGE("get vendor.connsys.fm.adie.chipid fail\n");
|
||||
}
|
||||
}
|
||||
|
||||
CUST_update_cfg(cfg, chipid);
|
||||
|
||||
return 0;
|
||||
}
|
547
libfmjni/fm.h
Executable file
547
libfmjni/fm.h
Executable file
|
@ -0,0 +1,547 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __FM_H__
|
||||
#define __FM_H__
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
typedef signed char fm_s8;
|
||||
typedef signed short fm_s16;
|
||||
typedef signed int fm_s32;
|
||||
typedef signed long long fm_s64;
|
||||
typedef unsigned char fm_u8;
|
||||
typedef unsigned short fm_u16;
|
||||
typedef unsigned int fm_u32;
|
||||
typedef unsigned long long fm_u64;
|
||||
typedef enum fm_bool {
|
||||
fm_false = 0,
|
||||
fm_true = 1
|
||||
} fm_bool;
|
||||
|
||||
// scan sort algorithm
|
||||
enum {
|
||||
FM_SCAN_SORT_NON = 0,
|
||||
FM_SCAN_SORT_UP,
|
||||
FM_SCAN_SORT_DOWN,
|
||||
FM_SCAN_SORT_MAX
|
||||
};
|
||||
|
||||
// scan methods
|
||||
enum {
|
||||
FM_SCAN_SEL_HW = 0, // select hardware scan, advantage: fast
|
||||
FM_SCAN_SEL_SW, // select software scan, advantage: more accurate
|
||||
FM_SCAN_SEL_MAX
|
||||
};
|
||||
|
||||
//*****************************************************************************************
|
||||
//***********************************FM config for customer *******************************
|
||||
//*****************************************************************************************
|
||||
#define FMR_RSSI_TH_LONG 0x0301 // FM radio long antenna RSSI threshold(11.375dBuV)
|
||||
#define FMR_RSSI_TH_SHORT 0x02E0 // FM radio short antenna RSSI threshold(-1dBuV)
|
||||
#define FMR_CQI_TH 0x00E9 // FM radio Channel quality indicator threshold(0x0000~0x00FF)
|
||||
#define FMR_SEEK_SPACE 1 // FM radio seek space,1:100KHZ; 2:200KHZ
|
||||
#define FMR_SCAN_CH_SIZE 40 // FM radio scan max channel size
|
||||
#define FMR_BAND 1 // FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz;
|
||||
// 3:76.0MHz~108.0MHz; 4:special
|
||||
#define FMR_BAND_FREQ_L 875 // FM radio special band low freq(Default 87.5MHz)
|
||||
#define FMR_BAND_FREQ_H 1080 // FM radio special band high freq(Default 108.0MHz)
|
||||
#define FM_SCAN_SORT_SELECT FM_SCAN_SORT_NON
|
||||
#define FM_SCAN_SELECT FM_SCAN_SEL_HW
|
||||
#define FM_SCAN_SOFT_MUTE_GAIN_TH 3 // soft-mute threshold when software scan, rang: 0~3,
|
||||
// 0 means better audio quality but less channel
|
||||
#define FM_CHIP_DESE_RSSI_TH (-102) // rang: -102 ~ -72
|
||||
|
||||
//*****************************************************************************************
|
||||
//***********************************FM config for engineer *******************************
|
||||
//*****************************************************************************************
|
||||
#define FMR_MR_TH 0x01BD // FM radio MR threshold
|
||||
#define ADDR_SCAN_TH 0xE0 // scan thrshold register
|
||||
#define ADDR_CQI_TH 0xE1 // scan CQI register
|
||||
//*****************************************************************************************
|
||||
|
||||
#define FM_NAME "fm"
|
||||
#define FM_DEVICE_NAME "/dev/fm"
|
||||
|
||||
// errno
|
||||
#define FM_SUCCESS 0
|
||||
#define FM_FAILED 1
|
||||
#define FM_EPARM 2
|
||||
#define FM_BADSTATUS 3
|
||||
#define FM_TUNE_FAILED 4
|
||||
#define FM_SEEK_FAILED 5
|
||||
#define FM_BUSY 6
|
||||
#define FM_SCAN_FAILED 7
|
||||
|
||||
// band
|
||||
#define FM_BAND_UNKNOWN 0
|
||||
#define FM_BAND_UE 1 // US/Europe band 87.5MHz ~ 108MHz (DEFAULT)
|
||||
#define FM_BAND_JAPAN 2 // Japan band 76MHz ~ 90MHz
|
||||
#define FM_BAND_JAPANW 3 // Japan wideband 76MHZ ~ 108MHz
|
||||
#define FM_BAND_SPECIAL 4 // special band between 76MHZ and 108MHz
|
||||
#define FM_BAND_DEFAULT FM_BAND_UE
|
||||
|
||||
#define FM_UE_FREQ_MIN 875
|
||||
#define FM_UE_FREQ_MAX 1080
|
||||
#define FM_JP_FREQ_MIN 760
|
||||
#define FM_JP_FREQ_MAX 1080
|
||||
#define FM_FREQ_MIN FMR_BAND_FREQ_L
|
||||
#define FM_FREQ_MAX FMR_BAND_FREQ_H
|
||||
#define FM_RAIDO_BAND FM_BAND_UE
|
||||
|
||||
// space
|
||||
#define FM_SPACE_UNKNOWN 0
|
||||
#define FM_SPACE_100K 1
|
||||
#define FM_SPACE_200K 2
|
||||
#define FM_SPACE_50K 5
|
||||
#define FM_SPACE_DEFAULT FM_SPACE_100K
|
||||
|
||||
#define FM_SEEK_SPACE FMR_SEEK_SPACE
|
||||
|
||||
// max scan channel num
|
||||
#define FM_MAX_CHL_SIZE FMR_SCAN_CH_SIZE
|
||||
// auto HiLo
|
||||
#define FM_AUTO_HILO_OFF 0
|
||||
#define FM_AUTO_HILO_ON 1
|
||||
|
||||
// seek direction
|
||||
#define FM_SEEK_UP 0
|
||||
#define FM_SEEK_DOWN 1
|
||||
|
||||
// seek threshold
|
||||
#define FM_SEEKTH_LEVEL_DEFAULT 4
|
||||
|
||||
struct fm_tune_parm {
|
||||
uint8_t err;
|
||||
uint8_t band;
|
||||
uint8_t space;
|
||||
uint8_t hilo;
|
||||
uint8_t deemphasis;
|
||||
uint16_t freq;
|
||||
};
|
||||
|
||||
struct fm_seek_parm {
|
||||
uint8_t err;
|
||||
uint8_t band;
|
||||
uint8_t space;
|
||||
uint8_t hilo;
|
||||
uint8_t seekdir;
|
||||
uint8_t seekth;
|
||||
uint16_t freq;
|
||||
};
|
||||
|
||||
struct fm_scan_parm {
|
||||
uint8_t err;
|
||||
uint8_t band;
|
||||
uint8_t space;
|
||||
uint8_t hilo;
|
||||
uint16_t freq;
|
||||
uint16_t ScanTBL[16];
|
||||
uint16_t ScanTBLSize;
|
||||
};
|
||||
|
||||
struct fm_ch_rssi {
|
||||
uint16_t freq;
|
||||
int rssi;
|
||||
};
|
||||
|
||||
enum fm_scan_cmd_t {
|
||||
FM_SCAN_CMD_INIT = 0,
|
||||
FM_SCAN_CMD_START,
|
||||
FM_SCAN_CMD_GET_NUM,
|
||||
FM_SCAN_CMD_GET_CH,
|
||||
FM_SCAN_CMD_GET_RSSI,
|
||||
FM_SCAN_CMD_GET_CH_RSSI,
|
||||
FM_SCAN_CMD_MAX
|
||||
};
|
||||
|
||||
struct fm_scan_t {
|
||||
enum fm_scan_cmd_t cmd;
|
||||
int ret; // 0, success; else error code
|
||||
uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz
|
||||
uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz
|
||||
int space; // 5: 50KHz, 10: 100Khz, 20: 200Khz
|
||||
int num; // valid channel number
|
||||
void *priv;
|
||||
int sr_size; // scan result buffer size in bytes
|
||||
union {
|
||||
uint16_t *ch_buf; // channel buffer
|
||||
int *rssi_buf; // rssi buffer
|
||||
struct fm_ch_rssi *ch_rssi_buf; //channel and RSSI buffer
|
||||
} sr;
|
||||
};
|
||||
|
||||
struct fm_seek_t {
|
||||
int ret; // 0, success; else error code
|
||||
uint16_t freq;
|
||||
uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz
|
||||
uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz
|
||||
int space; // 5: 50KHz, 10: 100Khz, 20: 200Khz
|
||||
int dir; // 0: up; 1: down
|
||||
int th; // seek threshold in dbm(Eg, -95dbm)
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct fm_tune_t {
|
||||
int ret; // 0, success; else error code
|
||||
uint16_t freq;
|
||||
uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz
|
||||
uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz
|
||||
int space; // 5: 50KHz, 10: 100Khz, 20: 200Khz
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct fm_softmute_tune_t {
|
||||
fm_s32 rssi; // RSSI of current channel
|
||||
fm_u16 freq; // current frequency
|
||||
fm_bool valid; // current channel is valid(true) or not(false)
|
||||
};
|
||||
|
||||
struct fm_rssi_req {
|
||||
uint16_t num;
|
||||
uint16_t read_cnt;
|
||||
struct fm_ch_rssi cr[16*16];
|
||||
};
|
||||
|
||||
struct fm_hw_info {
|
||||
int chip_id;
|
||||
int eco_ver;
|
||||
int rom_ver;
|
||||
int patch_ver;
|
||||
int reserve;
|
||||
};
|
||||
|
||||
struct fm_search_threshold_t {
|
||||
fm_s32 th_type;// 0, RSSI. 1,desense RSSI. 2,SMG.
|
||||
fm_s32 th_val; //threshold value
|
||||
fm_s32 reserve;
|
||||
};
|
||||
|
||||
#define NEED_DEF_RDS 1
|
||||
|
||||
#if NEED_DEF_RDS
|
||||
//For RDS feature
|
||||
typedef struct {
|
||||
uint8_t TP;
|
||||
uint8_t TA;
|
||||
uint8_t Music;
|
||||
uint8_t Stereo;
|
||||
uint8_t Artificial_Head;
|
||||
uint8_t Compressed;
|
||||
uint8_t Dynamic_PTY;
|
||||
uint8_t Text_AB;
|
||||
uint32_t flag_status;
|
||||
} RDSFlag_Struct;
|
||||
|
||||
typedef struct {
|
||||
uint16_t Month;
|
||||
uint16_t Day;
|
||||
uint16_t Year;
|
||||
uint16_t Hour;
|
||||
uint16_t Minute;
|
||||
uint8_t Local_Time_offset_signbit;
|
||||
uint8_t Local_Time_offset_half_hour;
|
||||
} CT_Struct;
|
||||
|
||||
typedef struct {
|
||||
int16_t AF_Num;
|
||||
int16_t AF[2][25];
|
||||
uint8_t Addr_Cnt;
|
||||
uint8_t isMethod_A;
|
||||
uint8_t isAFNum_Get;
|
||||
} AF_Info;
|
||||
|
||||
typedef struct {
|
||||
uint8_t PS[4][8];
|
||||
uint8_t Addr_Cnt;
|
||||
} PS_Info;
|
||||
|
||||
typedef struct {
|
||||
uint8_t TextData[4][64];
|
||||
uint8_t GetLength;
|
||||
uint8_t isRTDisplay;
|
||||
uint8_t TextLength;
|
||||
uint8_t isTypeA;
|
||||
uint8_t BufCnt;
|
||||
uint16_t Addr_Cnt;
|
||||
} RT_Info;
|
||||
|
||||
struct rds_raw_data {
|
||||
int dirty; // indicate if the data changed or not
|
||||
int len; // the data len form chip
|
||||
uint8_t data[148];
|
||||
};
|
||||
|
||||
struct rds_group_cnt {
|
||||
unsigned int total;
|
||||
unsigned int groupA[16]; // RDS groupA counter
|
||||
unsigned int groupB[16]; // RDS groupB counter
|
||||
};
|
||||
|
||||
enum rds_group_cnt_opcode {
|
||||
RDS_GROUP_CNT_READ = 0,
|
||||
RDS_GROUP_CNT_WRITE,
|
||||
RDS_GROUP_CNT_RESET,
|
||||
RDS_GROUP_CNT_MAX
|
||||
};
|
||||
|
||||
struct rds_group_cnt_req {
|
||||
int err;
|
||||
enum rds_group_cnt_opcode op;
|
||||
struct rds_group_cnt gc;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
CT_Struct CT;
|
||||
RDSFlag_Struct RDSFlag;
|
||||
uint16_t PI;
|
||||
uint8_t Switch_TP;
|
||||
uint8_t PTY;
|
||||
AF_Info AF_Data;
|
||||
AF_Info AFON_Data;
|
||||
uint8_t Radio_Page_Code;
|
||||
uint16_t Program_Item_Number_Code;
|
||||
uint8_t Extend_Country_Code;
|
||||
uint16_t Language_Code;
|
||||
PS_Info PS_Data;
|
||||
uint8_t PS_ON[8];
|
||||
RT_Info RT_Data;
|
||||
uint16_t event_status;
|
||||
struct rds_group_cnt gc;
|
||||
} RDSData_Struct;
|
||||
|
||||
//valid Rds Flag for notify
|
||||
typedef enum {
|
||||
RDS_FLAG_IS_TP = 0x0001, // Program is a traffic program
|
||||
RDS_FLAG_IS_TA = 0x0002, // Program currently broadcasts a traffic ann.
|
||||
RDS_FLAG_IS_MUSIC = 0x0004, // Program currently broadcasts music
|
||||
RDS_FLAG_IS_STEREO = 0x0008, // Program is transmitted in stereo
|
||||
RDS_FLAG_IS_ARTIFICIAL_HEAD = 0x0010, // Program is an artificial head recording
|
||||
RDS_FLAG_IS_COMPRESSED = 0x0020, // Program content is compressed
|
||||
RDS_FLAG_IS_DYNAMIC_PTY = 0x0040, // Program type can change
|
||||
RDS_FLAG_TEXT_AB = 0x0080 // If this flag changes state, a new radio text string begins
|
||||
} RdsFlag;
|
||||
|
||||
typedef enum {
|
||||
RDS_EVENT_FLAGS = 0x0001, // One of the RDS flags has changed state
|
||||
RDS_EVENT_PI_CODE = 0x0002, // The program identification code has changed
|
||||
RDS_EVENT_PTY_CODE = 0x0004, // The program type code has changed
|
||||
RDS_EVENT_PROGRAMNAME = 0x0008, // The program name has changed
|
||||
RDS_EVENT_UTCDATETIME = 0x0010, // A new UTC date/time is available
|
||||
RDS_EVENT_LOCDATETIME = 0x0020, // A new local date/time is available
|
||||
RDS_EVENT_LAST_RADIOTEXT = 0x0040, // A radio text string was completed
|
||||
RDS_EVENT_AF = 0x0080, // Current Channel RF signal strength too weak, need do AF switch
|
||||
RDS_EVENT_AF_LIST = 0x0100, // An alternative frequency list is ready
|
||||
RDS_EVENT_AFON_LIST = 0x0200, // An alternative frequency list is ready
|
||||
RDS_EVENT_TAON = 0x0400, // Other Network traffic announcement start
|
||||
RDS_EVENT_TAON_OFF = 0x0800, // Other Network traffic announcement finished.
|
||||
RDS_EVENT_ECC_CODE = 0x1000, /* ECC code */
|
||||
RDS_EVENT_RDS = 0x2000, // RDS Interrupt had arrived durint timer period
|
||||
RDS_EVENT_NO_RDS = 0x4000, // RDS Interrupt not arrived durint timer period
|
||||
RDS_EVENT_RDS_TIMER = 0x8000 // Timer for RDS Bler Check. ---- BLER block error rate
|
||||
} RdsEvent;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
FM_I2S_ON = 0,
|
||||
FM_I2S_OFF,
|
||||
FM_I2S_STATE_ERR
|
||||
} fm_i2s_state_e;
|
||||
|
||||
typedef enum {
|
||||
FM_I2S_MASTER = 0,
|
||||
FM_I2S_SLAVE,
|
||||
FM_I2S_MODE_ERR
|
||||
} fm_i2s_mode_e;
|
||||
|
||||
typedef enum {
|
||||
FM_I2S_32K = 0,
|
||||
FM_I2S_44K,
|
||||
FM_I2S_48K,
|
||||
FM_I2S_SR_ERR
|
||||
} fm_i2s_sample_e;
|
||||
|
||||
struct fm_i2s_setting {
|
||||
int onoff;
|
||||
int mode;
|
||||
int sample;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
FM_RX = 0,
|
||||
FM_TX = 1
|
||||
} FM_PWR_T;
|
||||
|
||||
typedef struct fm_i2s_info {
|
||||
int status; /* 0:FM_I2S_ON, 1:FM_I2S_OFF,2:error */
|
||||
int mode; /* 0:FM_I2S_MASTER, 1:FM_I2S_SLAVE,2:error */
|
||||
int rate; /* 0:FM_I2S_32K:32000,1:FM_I2S_44K:44100,2:FM_I2S_48K:48000,3:error */
|
||||
} fm_i2s_info_t;
|
||||
|
||||
typedef enum {
|
||||
FM_AUD_ANALOG = 0,
|
||||
FM_AUD_I2S = 1,
|
||||
FM_AUD_MRGIF = 2,
|
||||
FM_AUD_ERR
|
||||
} fm_audio_path_e;
|
||||
|
||||
typedef enum {
|
||||
FM_I2S_PAD_CONN = 0,
|
||||
FM_I2S_PAD_IO = 1,
|
||||
FM_I2S_PAD_ERR
|
||||
} fm_i2s_pad_sel_e;
|
||||
|
||||
typedef struct fm_audio_info {
|
||||
fm_audio_path_e aud_path;
|
||||
fm_i2s_info_t i2s_info;
|
||||
fm_i2s_pad_sel_e i2s_pad;
|
||||
} fm_audio_info_t;
|
||||
|
||||
struct fm_cqi {
|
||||
int ch;
|
||||
int rssi;
|
||||
int reserve;
|
||||
};
|
||||
|
||||
struct fm_cqi_req {
|
||||
uint16_t ch_num;
|
||||
int buf_size;
|
||||
char *cqi_buf;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int freq;
|
||||
int rssi;
|
||||
} fm_desense_check_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz
|
||||
uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz
|
||||
int space; // 0x1: 50KHz, 0x2: 100Khz, 0x4: 200Khz
|
||||
int cycle; // repeat times
|
||||
} fm_full_cqi_log_t;
|
||||
|
||||
// ********** ***********FM IOCTL define start *******************************
|
||||
#define FM_IOC_MAGIC 0xf5
|
||||
#define FM_IOCTL_POWERUP _IOWR(FM_IOC_MAGIC, 0, struct fm_tune_parm*)
|
||||
#define FM_IOCTL_POWERDOWN _IOWR(FM_IOC_MAGIC, 1, int32_t*)
|
||||
#define FM_IOCTL_TUNE _IOWR(FM_IOC_MAGIC, 2, struct fm_tune_parm*)
|
||||
#define FM_IOCTL_SEEK _IOWR(FM_IOC_MAGIC, 3, struct fm_seek_parm*)
|
||||
#define FM_IOCTL_SETVOL _IOWR(FM_IOC_MAGIC, 4, uint32_t*)
|
||||
#define FM_IOCTL_GETVOL _IOWR(FM_IOC_MAGIC, 5, uint32_t*)
|
||||
#define FM_IOCTL_MUTE _IOWR(FM_IOC_MAGIC, 6, uint32_t*)
|
||||
#define FM_IOCTL_GETRSSI _IOWR(FM_IOC_MAGIC, 7, int32_t*)
|
||||
#define FM_IOCTL_SCAN _IOWR(FM_IOC_MAGIC, 8, struct fm_scan_parm*)
|
||||
#define FM_IOCTL_STOP_SCAN _IO(FM_IOC_MAGIC, 9)
|
||||
|
||||
//IOCTL and struct for test
|
||||
#define FM_IOCTL_GETCHIPID _IOWR(FM_IOC_MAGIC, 10, uint16_t*)
|
||||
#define FM_IOCTL_EM_TEST _IOWR(FM_IOC_MAGIC, 11, struct fm_em_parm*)
|
||||
#define FM_IOCTL_RW_REG _IOWR(FM_IOC_MAGIC, 12, struct fm_ctl_parm*)
|
||||
#define FM_IOCTL_GETMONOSTERO _IOWR(FM_IOC_MAGIC, 13, uint16_t*)
|
||||
#define FM_IOCTL_GETCURPAMD _IOWR(FM_IOC_MAGIC, 14, uint16_t*)
|
||||
#define FM_IOCTL_GETGOODBCNT _IOWR(FM_IOC_MAGIC, 15, uint16_t*)
|
||||
#define FM_IOCTL_GETBADBNT _IOWR(FM_IOC_MAGIC, 16, uint16_t*)
|
||||
#define FM_IOCTL_GETBLERRATIO _IOWR(FM_IOC_MAGIC, 17, uint16_t*)
|
||||
|
||||
//IOCTL for RDS
|
||||
#define FM_IOCTL_RDS_ONOFF _IOWR(FM_IOC_MAGIC, 18, uint16_t*)
|
||||
#define FM_IOCTL_RDS_SUPPORT _IOWR(FM_IOC_MAGIC, 19, int32_t*)
|
||||
|
||||
#define FM_IOCTL_RDS_SIM_DATA _IOWR(FM_IOC_MAGIC, 23, uint32_t*)
|
||||
#define FM_IOCTL_IS_FM_POWERED_UP _IOWR(FM_IOC_MAGIC, 24, uint32_t*)
|
||||
|
||||
//IOCTL for FM over BT
|
||||
#define FM_IOCTL_OVER_BT_ENABLE _IOWR(FM_IOC_MAGIC, 29, int32_t*)
|
||||
|
||||
//IOCTL for FM ANTENNA SWITCH
|
||||
#define FM_IOCTL_ANA_SWITCH _IOWR(FM_IOC_MAGIC, 30, int32_t*)
|
||||
#define FM_IOCTL_GETCAPARRAY _IOWR(FM_IOC_MAGIC, 31, int32_t*)
|
||||
|
||||
//IOCTL for FM I2S Setting
|
||||
#define FM_IOCTL_I2S_SETTING _IOWR(FM_IOC_MAGIC, 33, struct fm_i2s_setting*)
|
||||
|
||||
#define FM_IOCTL_RDS_GROUPCNT _IOWR(FM_IOC_MAGIC, 34, struct rds_group_cnt_req*)
|
||||
#define FM_IOCTL_RDS_GET_LOG _IOWR(FM_IOC_MAGIC, 35, struct rds_raw_data*)
|
||||
|
||||
#define FM_IOCTL_SCAN_GETRSSI _IOWR(FM_IOC_MAGIC, 36, struct fm_rssi_req*)
|
||||
#define FM_IOCTL_SETMONOSTERO _IOWR(FM_IOC_MAGIC, 37, int32_t)
|
||||
#define FM_IOCTL_RDS_BC_RST _IOWR(FM_IOC_MAGIC, 38, int32_t*)
|
||||
#define FM_IOCTL_CQI_GET _IOWR(FM_IOC_MAGIC, 39, struct fm_cqi_req*)
|
||||
#define FM_IOCTL_GET_HW_INFO _IOWR(FM_IOC_MAGIC, 40, struct fm_hw_info*)
|
||||
#define FM_IOCTL_GET_I2S_INFO _IOWR(FM_IOC_MAGIC, 41, fm_i2s_info_t*)
|
||||
#define FM_IOCTL_IS_DESE_CHAN _IOWR(FM_IOC_MAGIC, 42, int32_t*)
|
||||
#define FM_IOCTL_TOP_RDWR _IOWR(FM_IOC_MAGIC, 43, struct fm_top_rw_parm*)
|
||||
#define FM_IOCTL_HOST_RDWR _IOWR(FM_IOC_MAGIC, 44, struct fm_host_rw_parm*)
|
||||
|
||||
#define FM_IOCTL_PRE_SEARCH _IOWR(FM_IOC_MAGIC, 45,int32_t)
|
||||
#define FM_IOCTL_RESTORE_SEARCH _IOWR(FM_IOC_MAGIC, 46,int32_t)
|
||||
|
||||
#define FM_IOCTL_SET_SEARCH_THRESHOLD _IOWR(FM_IOC_MAGIC, 47, fm_search_threshold_t*)
|
||||
|
||||
#define FM_IOCTL_GET_AUDIO_INFO _IOWR(FM_IOC_MAGIC, 48, fm_audio_info_t*)
|
||||
|
||||
#define FM_IOCTL_SCAN_NEW _IOWR(FM_IOC_MAGIC, 60, struct fm_scan_t*)
|
||||
#define FM_IOCTL_SEEK_NEW _IOWR(FM_IOC_MAGIC, 61, struct fm_seek_t*)
|
||||
#define FM_IOCTL_TUNE_NEW _IOWR(FM_IOC_MAGIC, 62, struct fm_tune_t*)
|
||||
|
||||
#define FM_IOCTL_SOFT_MUTE_TUNE _IOWR(FM_IOC_MAGIC, 63, struct fm_softmute_tune_t*)/*for soft mute tune*/
|
||||
#define FM_IOCTL_DESENSE_CHECK _IOWR(FM_IOC_MAGIC, 64, fm_desense_check_t*)
|
||||
|
||||
//IOCTL for EM
|
||||
#define FM_IOCTL_FULL_CQI_LOG _IOWR(FM_IOC_MAGIC, 70, fm_full_cqi_log_t *)
|
||||
|
||||
#define FM_IOCTL_DUMP_REG _IO(FM_IOC_MAGIC, 0xFF)
|
||||
// ********** ***********FM IOCTL define end *******************************
|
||||
|
||||
enum group_idx {
|
||||
mono = 0,
|
||||
stereo,
|
||||
RSSI_threshold,
|
||||
HCC_Enable,
|
||||
PAMD_threshold,
|
||||
Softmute_Enable,
|
||||
De_emphasis,
|
||||
HL_Side,
|
||||
Demod_BW,
|
||||
Dynamic_Limiter,
|
||||
Softmute_Rate,
|
||||
AFC_Enable,
|
||||
Softmute_Level,
|
||||
Analog_Volume,
|
||||
GROUP_TOTAL_NUMS
|
||||
};
|
||||
|
||||
enum item_idx {
|
||||
Sblend_OFF = 0,
|
||||
Sblend_ON,
|
||||
ITEM_TOTAL_NUMS
|
||||
};
|
||||
|
||||
struct fm_ctl_parm {
|
||||
uint8_t err;
|
||||
uint8_t addr;
|
||||
uint16_t val;
|
||||
uint16_t rw_flag; // 0:write, 1:read
|
||||
};
|
||||
|
||||
struct fm_em_parm {
|
||||
uint16_t group_idx;
|
||||
uint16_t item_idx;
|
||||
uint32_t item_value;
|
||||
};
|
||||
#endif // __FM_H__
|
66
libfmjni/fmlib_cust.h
Normal file
66
libfmjni/fmlib_cust.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Copyright Statement:
|
||||
*
|
||||
* This software/firmware and related documentation ("MediaTek Software") are
|
||||
* protected under relevant copyright laws. The information contained herein is
|
||||
* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
|
||||
* the prior written permission of MediaTek inc. and/or its licensors, any
|
||||
* reproduction, modification, use or disclosure of MediaTek Software, and
|
||||
* information contained herein, in whole or in part, shall be strictly
|
||||
* prohibited.
|
||||
*
|
||||
* MediaTek Inc. (C) 2010. All rights reserved.
|
||||
*
|
||||
* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
|
||||
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
|
||||
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
|
||||
* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
|
||||
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||
* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
|
||||
* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
|
||||
* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
|
||||
* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
|
||||
* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
|
||||
* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
|
||||
* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
|
||||
* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
|
||||
* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
|
||||
* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
|
||||
* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
|
||||
* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
|
||||
* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
|
||||
*
|
||||
* The following software/firmware and/or related documentation ("MediaTek
|
||||
* Software") have been modified by MediaTek Inc. All revisions are subject to
|
||||
* any receiver's applicable license agreements with MediaTek Inc.
|
||||
*/
|
||||
|
||||
#ifndef __FMLIB_CUST_H__
|
||||
#define __FMLIB_CUST_H__
|
||||
|
||||
#define FM_CHIP_MT6616 0x6616
|
||||
#define FM_CHIP_MT6620 0x6620
|
||||
#define FM_CHIP_MT6626 0x6626
|
||||
#define FM_CHIP_MT6628 0x6628
|
||||
#define FM_CHIP_MT6627 0x6627
|
||||
#define FM_CHIP_MT6580 0x6580
|
||||
#define FM_CHIP_MT6630 0x6630
|
||||
#define FM_CHIP_MT6631 0x6631
|
||||
#define FM_CHIP_MT6632 0x6632
|
||||
#define FM_CHIP_MT6635 0x6635
|
||||
|
||||
#define FM_CHIP_UNSUPPORTED -1
|
||||
|
||||
#define FM_JNI_SCAN_SPACE_50K 5
|
||||
#define FM_JNI_SCAN_SPACE_100K 1
|
||||
#define FM_JNI_SCAN_SPACE_200K 2
|
||||
|
||||
/*implement fm scan by soft mute tune
|
||||
change to 0 will scan by orginal way*/
|
||||
#define FMR_SOFT_MUTE_TUEN_SCAN 1
|
||||
#define FMR_NOISE_FLOORT_DETECT 1
|
||||
#define RSSI_TH -296
|
||||
#define FM_SEVERE_RSSI_TH -107 // 67dBuV
|
||||
#define FM_NOISE_FLOOR_OFFSET 10
|
||||
|
||||
#endif // __FMLIB_CUST_H__
|
276
libfmjni/fmr.h
Executable file
276
libfmjni/fmr.h
Executable file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __FMR_H__
|
||||
#define __FMR_H__
|
||||
|
||||
#include <jni.h>
|
||||
#include <utils/Log.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "fm.h"
|
||||
#include "fmlib_cust.h"
|
||||
|
||||
#undef LOGV
|
||||
#define LOGV(...) ALOGV(__VA_ARGS__)
|
||||
#undef LOGD
|
||||
#define LOGD(...) ALOGD(__VA_ARGS__)
|
||||
#undef LOGI
|
||||
#define LOGI(...) ALOGI(__VA_ARGS__)
|
||||
#undef LOGW
|
||||
#define LOGW(...) ALOGW(__VA_ARGS__)
|
||||
#undef LOGE
|
||||
#define LOGE(...) ALOGE(__VA_ARGS__)
|
||||
|
||||
|
||||
#define FM_DEV_NAME "/dev/fm"
|
||||
|
||||
#define FM_RDS_PS_LEN 8
|
||||
|
||||
struct fm_fake_channel
|
||||
{
|
||||
int freq;
|
||||
int rssi_th;
|
||||
int reserve;
|
||||
};
|
||||
|
||||
struct fm_fake_channel_t
|
||||
{
|
||||
int size;
|
||||
struct fm_fake_channel *chan;
|
||||
};
|
||||
|
||||
struct CUST_cfg_ds
|
||||
{
|
||||
int16_t chip;
|
||||
int32_t band;
|
||||
int32_t low_band;
|
||||
int32_t high_band;
|
||||
int32_t seek_space;
|
||||
int32_t max_scan_num;
|
||||
int32_t seek_lev;
|
||||
int32_t scan_sort;
|
||||
int32_t short_ana_sup;
|
||||
int32_t rssi_th_l2;
|
||||
struct fm_fake_channel_t *fake_chan;
|
||||
};
|
||||
|
||||
struct fm_cbk_tbl {
|
||||
//Basic functions.
|
||||
int (*open_dev)(const char *pname, int *fd);
|
||||
int (*close_dev)(int fd);
|
||||
int (*pwr_up)(int fd, int band, int freq);
|
||||
int (*pwr_down)(int fd, int type);
|
||||
int (*seek)(int fd, int *freq, int band, int dir, int lev);
|
||||
int (*scan)(int fd, uint16_t *tbl, int *num, int band, int sort);
|
||||
int (*fastget_rssi)(int fd, struct fm_rssi_req *rssi_req);
|
||||
int (*get_cqi)(int fd, int num, char *buf, int buf_len);
|
||||
int (*stop_scan)(int fd);
|
||||
int (*tune)(int fd, int freq, int band);
|
||||
int (*set_mute)(int fd, int mute);
|
||||
int (*is_fm_pwrup)(int fd, int *pwrup);
|
||||
int (*is_rdsrx_support)(int fd, int *supt);
|
||||
int (*turn_on_off_rds)(int fd, int onoff);
|
||||
int (*get_chip_id)(int fd, int *chipid);
|
||||
//FOR RDS RX.
|
||||
int (*read_rds_data)(int fd, RDSData_Struct *rds, uint16_t *rds_status);
|
||||
int (*get_pi)(int fd, RDSData_Struct *rds, uint16_t *pi);
|
||||
int (*get_ecc)(int fd, RDSData_Struct *rds, uint8_t *ecc);
|
||||
int (*get_ps)(int fd, RDSData_Struct *rds, uint8_t **ps, int *ps_len);
|
||||
int (*get_pty)(int fd, RDSData_Struct *rds, uint8_t *pty);
|
||||
int (*get_rssi)(int fd, int *rssi);
|
||||
int (*get_rt)(int fd, RDSData_Struct *rds, uint8_t **rt, int *rt_len);
|
||||
int (*active_af)(int fd, RDSData_Struct *rds, CUST_cfg_ds *cfg, uint16_t orig_pi, uint16_t cur_freq, uint16_t *ret_freq);
|
||||
int (*active_ta)(int fd, RDSData_Struct *rds, int band, uint16_t cur_freq, uint16_t *backup_freq, uint16_t *ret_freq);
|
||||
int (*deactive_ta)(int fd, RDSData_Struct *rds, int band, uint16_t cur_freq, uint16_t *backup_freq, uint16_t *ret_freq);
|
||||
//FM long/short antenna switch
|
||||
int (*ana_switch)(int fd, int antenna);
|
||||
//For FM RX EM mode
|
||||
int (*get_badratio)(int fd, int *badratio);
|
||||
int (*get_stereomono)(int fd, int *stemono);
|
||||
int (*set_stereomono)(int fd, int stemono);
|
||||
int (*get_caparray)(int fd, int *caparray);
|
||||
int (*get_hw_info)(int fd, struct fm_hw_info *info);
|
||||
int (*is_dese_chan)(int fd, int freq);
|
||||
int (*soft_mute_tune)(int fd, fm_softmute_tune_t *para);
|
||||
int (*desense_check)(int fd, int freq, int rssi);
|
||||
int (*set_search_threshold)(int fd, int th_idx,int th_val);
|
||||
int (*full_cqi_logger)(int fd,fm_full_cqi_log_t *log_parm);
|
||||
/*New search*/
|
||||
int (*pre_search)(int fd);
|
||||
int (*restore_search)(int fd);
|
||||
};
|
||||
|
||||
typedef int (*CUST_func_type)(struct CUST_cfg_ds *);
|
||||
typedef void (*init_func_type)(struct fm_cbk_tbl *);
|
||||
|
||||
struct fmr_ds {
|
||||
int fd;
|
||||
int err;
|
||||
uint16_t cur_freq;
|
||||
uint16_t backup_freq;
|
||||
void *priv;
|
||||
void *custom_handler;
|
||||
struct CUST_cfg_ds cfg_data;
|
||||
struct fm_cbk_tbl tbl;
|
||||
CUST_func_type get_cfg;
|
||||
void *init_handler;
|
||||
init_func_type init_func;
|
||||
RDSData_Struct rds;
|
||||
struct fm_hw_info hw_info;
|
||||
fm_bool scan_stop;
|
||||
};
|
||||
|
||||
enum fmr_err_em {
|
||||
ERR_SUCCESS = 1000, // kernel error begin at here
|
||||
ERR_INVALID_BUF,
|
||||
ERR_INVALID_PARA,
|
||||
ERR_STP,
|
||||
ERR_GET_MUTEX,
|
||||
ERR_FW_NORES,
|
||||
ERR_RDS_CRC,
|
||||
ERR_INVALID_FD, // native error begin at here
|
||||
ERR_UNSUPPORT_CHIP,
|
||||
ERR_LD_LIB,
|
||||
ERR_FIND_CUST_FNUC,
|
||||
ERR_UNINIT,
|
||||
ERR_NO_MORE_IDX,
|
||||
ERR_RDS_NO_DATA,
|
||||
ERR_UNSUPT_SHORTANA,
|
||||
ERR_MAX
|
||||
};
|
||||
|
||||
enum fmr_rds_onoff {
|
||||
FMR_RDS_ON,
|
||||
FMR_RDS_OFF,
|
||||
FMR_MAX
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
FM_LONG_ANA = 0,
|
||||
FM_SHORT_ANA
|
||||
} fm_antenna_type;
|
||||
|
||||
|
||||
#define CQI_CH_NUM_MAX 255
|
||||
#define CQI_CH_NUM_MIN 0
|
||||
|
||||
|
||||
/****************** Function declaration ******************/
|
||||
//fmr_err.cpp
|
||||
char *FMR_strerr();
|
||||
void FMR_seterr(int err);
|
||||
|
||||
//fmr_core.cpp
|
||||
int FMR_init(void);
|
||||
int FMR_get_cfgs(int idx);
|
||||
int FMR_open_dev(int idx);
|
||||
int FMR_close_dev(int idx);
|
||||
int FMR_pwr_up(int idx, int freq);
|
||||
int FMR_pwr_down(int idx, int type);
|
||||
int FMR_seek(int idx, int start_freq, int dir, int *ret_freq);
|
||||
int FMR_scan(int idx, uint16_t *tbl, int *num);
|
||||
int FMR_stop_scan(int idx);
|
||||
int FMR_tune(int idx, int freq);
|
||||
int FMR_set_mute(int idx, int mute);
|
||||
int FMR_is_fm_pwrup(int idx, int *pwrup);
|
||||
int FMR_is_rdsrx_support(int idx, int *supt);
|
||||
int FMR_turn_on_off_rds(int idx, int onoff);
|
||||
int FMR_get_chip_id(int idx, int *chipid);
|
||||
int FMR_read_rds_data(int idx, uint16_t *rds_status);
|
||||
int FMR_get_pi(int idx, uint16_t *pi);
|
||||
int FMR_get_ecc(int idx, uint8_t *ecc);
|
||||
int FMR_get_ps(int idx, uint8_t **ps, int *ps_len);
|
||||
int FMR_get_pty(int idx, uint8_t *pty);
|
||||
int FMR_get_rssi(int idx, int *rssi);
|
||||
int FMR_get_rt(int idx, uint8_t **rt, int *rt_len);
|
||||
int FMR_active_af(int idx, uint16_t orig_pi, uint16_t *ret_freq);
|
||||
int FMR_active_ta(int idx, uint16_t *ret_freq);
|
||||
int FMR_deactive_ta(int idx, uint16_t *ret_freq);
|
||||
|
||||
int FMR_ana_switch(int idx, int antenna);
|
||||
int FMR_get_badratio(int idx, int *badratio);
|
||||
int FMR_get_stereomono(int idx, int *stemono);
|
||||
int FMR_set_stereomono(int idx, int stemono);
|
||||
int FMR_get_caparray(int idx, int *caparray);
|
||||
int FMR_get_hw_info(int idx, int **info, int *info_len);
|
||||
int FMR_Pre_Search(int idx);
|
||||
int FMR_Restore_Search(int idx);
|
||||
int FMR_EMSetTH(int idx, int th_idx, int th_val);
|
||||
int FMR_EM_CQI_logger(int idx,uint16_t cycle);
|
||||
void FM_interface_init(struct fm_cbk_tbl *cbk_tbl);
|
||||
|
||||
//common part
|
||||
int COM_open_dev(const char *pname, int *fd);
|
||||
int COM_close_dev(int fd);
|
||||
int COM_pwr_up(int fd, int band, int freq);
|
||||
int COM_pwr_down(int fd, int type);
|
||||
int COM_seek(int fd, int *freq, int band, int dir, int lev);
|
||||
int COM_Soft_Mute_Tune(int fd, fm_softmute_tune_t *para);
|
||||
int COM_fastget_rssi(int fd, struct fm_rssi_req *rssi_req);
|
||||
int COM_get_cqi(int fd, int num, char *buf, int buf_len);
|
||||
int COM_stop_scan(int fd);
|
||||
int COM_tune(int fd, int freq, int band);
|
||||
int COM_set_mute(int fd, int mute);
|
||||
int COM_is_fm_pwrup(int fd, int *pwrup);
|
||||
int COM_is_rdsrx_support(int fd, int *supt);
|
||||
int COM_turn_on_off_rds(int fd, int onoff);
|
||||
int COM_get_chip_id(int fd, int *chipid);
|
||||
int COM_read_rds_data(int fd, RDSData_Struct *rds, uint16_t *rds_status);
|
||||
int COM_get_pi(int fd, RDSData_Struct *rds, uint16_t *pi);
|
||||
int COM_get_ps(int fd, RDSData_Struct *rds, uint8_t **ps, int *ps_len);
|
||||
int COM_get_pty(int fd, RDSData_Struct *rds, uint8_t *pty);
|
||||
int COM_get_rssi(int fd, int *rssi);
|
||||
int COM_get_rt(int fd, RDSData_Struct *rds, uint8_t **rt, int *rt_len);
|
||||
int COM_active_af(int fd, RDSData_Struct *rds, CUST_cfg_ds *cfg, uint16_t orig_pi, uint16_t cur_freq, uint16_t *ret_freq);
|
||||
int COM_active_ta(int fd, RDSData_Struct *rds, int band, uint16_t cur_freq, uint16_t *backup_freq, uint16_t *ret_freq);
|
||||
int COM_deactive_ta(int fd, RDSData_Struct *rds, int band, uint16_t cur_freq, uint16_t *backup_freq, uint16_t *ret_freq);
|
||||
int COM_ana_switch(int fd, int antenna);
|
||||
int COM_get_badratio(int fd, int *badratio);
|
||||
int COM_get_stereomono(int fd, int *stemono);
|
||||
int COM_set_stereomono(int fd, int stemono);
|
||||
int COM_get_caparray(int fd, int *caparray);
|
||||
int COM_get_hw_info(int fd, struct fm_hw_info *info);
|
||||
int COM_is_dese_chan(int fd, int freq);
|
||||
int COM_desense_check(int fd, int freq, int rssi);
|
||||
int COM_pre_search(int fd);
|
||||
int COM_restore_search(int fd);
|
||||
int COM_set_search_threshold(int fd, int th_idx,int th_val);
|
||||
int COM_full_cqi_logger(int fd, fm_full_cqi_log_t *log_parm);
|
||||
|
||||
void CUST_update_cfg(struct CUST_cfg_ds *cfg, int chipid);
|
||||
int CUST_get_cfg(struct CUST_cfg_ds *cfg);
|
||||
|
||||
#define FMR_ASSERT(a) { \
|
||||
if ((a) == NULL) { \
|
||||
LOGE("%s,invalid buf\n", __func__);\
|
||||
return -ERR_INVALID_BUF; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
1264
libfmjni/fmr_core.cpp
Executable file
1264
libfmjni/fmr_core.cpp
Executable file
File diff suppressed because it is too large
Load diff
45
libfmjni/fmr_err.cpp
Executable file
45
libfmjni/fmr_err.cpp
Executable file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "fmr.h"
|
||||
|
||||
#ifdef LOG_TAG
|
||||
#undef LOG_TAG
|
||||
#endif
|
||||
#define LOG_TAG "FMLIB_ERR"
|
||||
|
||||
#define FMR_ERR_BASE -0x100
|
||||
|
||||
static int fmr_err = 0;
|
||||
static char tmp[20] = {0};
|
||||
|
||||
char *FMR_strerr()
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = sprintf(tmp, "%d", fmr_err);
|
||||
if (ret < 0) {
|
||||
LOGE("%s sprintf fail\n", __func__);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void FMR_seterr(int err)
|
||||
{
|
||||
fmr_err = err;
|
||||
}
|
||||
|
806
libfmjni/libfm_jni.cpp
Executable file
806
libfmjni/libfm_jni.cpp
Executable file
|
@ -0,0 +1,806 @@
|
|||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include "fmr.h"
|
||||
|
||||
#ifdef LOG_TAG
|
||||
#undef LOG_TAG
|
||||
#endif
|
||||
#define LOG_TAG "FMLIB_JNI"
|
||||
#define FM_AF_THRESHOLD -80
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
static int g_idx = -1;
|
||||
extern struct fmr_ds fmr_data;
|
||||
static short g_CurrentRDS_PI;
|
||||
|
||||
jboolean openDev(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_open_dev(g_idx); // if success, then ret = 0; else ret < 0
|
||||
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return ret?JNI_FALSE:JNI_TRUE;
|
||||
}
|
||||
|
||||
jboolean closeDev(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_close_dev(g_idx);
|
||||
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return ret?JNI_FALSE:JNI_TRUE;
|
||||
}
|
||||
|
||||
jboolean powerUp(JNIEnv *env, jobject thiz, jfloat freq)
|
||||
{
|
||||
int ret = 0;
|
||||
int tmp_freq;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
LOGI("%s, [freq=%d]\n", __func__, (int)freq);
|
||||
/* fix jfloat precision issue */
|
||||
tmp_freq = (int)((float)freq * 100 + 0.5); //Eg, 87.5 * 100 --> 8750
|
||||
ret = FMR_pwr_up(g_idx, tmp_freq);
|
||||
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return ret?JNI_FALSE:JNI_TRUE;
|
||||
}
|
||||
|
||||
jboolean powerDown(JNIEnv *env, jobject thiz, jint type)
|
||||
{
|
||||
int ret = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_pwr_down(g_idx, type);
|
||||
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return ret?JNI_FALSE:JNI_TRUE;
|
||||
}
|
||||
|
||||
jint readRssi(JNIEnv *env, jobject thiz) //jint = int
|
||||
{
|
||||
int ret = 0;
|
||||
int rssi = -1;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_rssi(g_idx, &rssi);
|
||||
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return rssi;
|
||||
}
|
||||
|
||||
jboolean tune(JNIEnv *env, jobject thiz, jfloat freq)
|
||||
{
|
||||
int ret = 0;
|
||||
int tmp_freq;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
/* fix jfloat precision issue */
|
||||
tmp_freq = (int)((float)freq * 100 + 0.5); //Eg, 87.5 * 100 --> 8750
|
||||
ret = FMR_tune(g_idx, tmp_freq);
|
||||
if (!ret) /* clean global pi*/
|
||||
g_CurrentRDS_PI = 0;
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return ret?JNI_FALSE:JNI_TRUE;
|
||||
}
|
||||
|
||||
jfloat seek(JNIEnv *env, jobject thiz, jfloat freq, jboolean isUp) //jboolean isUp;
|
||||
{
|
||||
int ret = 0;
|
||||
int tmp_freq;
|
||||
int ret_freq;
|
||||
float val;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
/* fix jfloat precision issue */
|
||||
tmp_freq = (int)((float)freq * 100 + 0.5); //Eg, 87.5 * 100 --> 8750
|
||||
ret = FMR_set_mute(g_idx, 1);
|
||||
if (ret) {
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGD("%s, [mute] [ret=%d]\n", __func__, ret);
|
||||
|
||||
ret = FMR_seek(g_idx, tmp_freq, (int)isUp, &ret_freq);
|
||||
if (ret) {
|
||||
ret_freq = tmp_freq; //seek error, so use original freq
|
||||
}
|
||||
|
||||
LOGD("%s, [freq=%d] [ret=%d]\n", __func__, ret_freq, ret);
|
||||
|
||||
val = (float)ret_freq/100; //Eg, 8755 / 100 --> 87.55
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
jshortArray autoScan(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
#define FM_SCAN_CH_SIZE_MAX 200
|
||||
int ret = 0;
|
||||
jshortArray scanChlarray;
|
||||
int chl_cnt = FM_SCAN_CH_SIZE_MAX;
|
||||
uint16_t ScanTBL[FM_SCAN_CH_SIZE_MAX];
|
||||
UNUSED(thiz);
|
||||
|
||||
LOGI("%s, [tbl=%p]\n", __func__, ScanTBL);
|
||||
FMR_Pre_Search(g_idx);
|
||||
ret = FMR_scan(g_idx, ScanTBL, &chl_cnt);
|
||||
if (ret < 0) {
|
||||
LOGE("scan failed!\n");
|
||||
scanChlarray = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (chl_cnt > 0) {
|
||||
scanChlarray = env->NewShortArray(chl_cnt);
|
||||
env->SetShortArrayRegion(scanChlarray, 0, chl_cnt, (const jshort*)&ScanTBL[0]);
|
||||
} else {
|
||||
LOGE("cnt error, [cnt=%d]\n", chl_cnt);
|
||||
scanChlarray = NULL;
|
||||
}
|
||||
FMR_Restore_Search(g_idx);
|
||||
|
||||
if (fmr_data.scan_stop == fm_true) {
|
||||
ret = FMR_tune(g_idx, fmr_data.cur_freq);
|
||||
LOGI("scan stop!!! tune ret=%d",ret);
|
||||
scanChlarray = NULL;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
out:
|
||||
LOGD("%s, [cnt=%d] [ret=%d]\n", __func__, chl_cnt, ret);
|
||||
return scanChlarray;
|
||||
}
|
||||
|
||||
jboolean emsetth(JNIEnv *env, jobject thiz, jint index, jint value)
|
||||
{
|
||||
int ret = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_EMSetTH(g_idx, index, value);
|
||||
|
||||
LOGD("emsetth ret %d\n", ret);
|
||||
return (ret < 0) ? JNI_FALSE : JNI_TRUE;
|
||||
}
|
||||
jshortArray emcmd(JNIEnv *env, jobject thiz, jshortArray val)
|
||||
{
|
||||
jshortArray eventarray = NULL;
|
||||
uint16_t eventtbl[20]={0};
|
||||
uint16_t* cmdtbl=NULL;
|
||||
UNUSED(thiz);
|
||||
|
||||
cmdtbl = (uint16_t*) env->GetShortArrayElements(val, NULL);
|
||||
if(cmdtbl == NULL)
|
||||
{
|
||||
LOGE("%s:get cmdtbl error\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
LOGI("EM cmd:=%x %x %x %x %x",cmdtbl[0],cmdtbl[1],cmdtbl[2],cmdtbl[3],cmdtbl[4]);
|
||||
|
||||
if(!cmdtbl[0]) //LANT
|
||||
{
|
||||
}
|
||||
else //SANT
|
||||
{
|
||||
}
|
||||
|
||||
switch(cmdtbl[1])
|
||||
{
|
||||
case 0x02: //CQI log tool
|
||||
{
|
||||
FMR_EM_CQI_logger(g_idx, cmdtbl[2]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
eventarray = env->NewShortArray(20);
|
||||
env->SetShortArrayRegion(eventarray, 0, 20, (const jshort*)&eventtbl[0]);
|
||||
//LOGD("emsetth ret %d\n", ret);
|
||||
out:
|
||||
return eventarray;
|
||||
}
|
||||
|
||||
jshort readRds(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
int rssi = -1;
|
||||
uint16_t rds_status = 0;
|
||||
uint16_t pi = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_read_rds_data(g_idx, &rds_status);
|
||||
|
||||
if (ret) {
|
||||
rds_status = 0; // There's no event or some error happened
|
||||
} else {
|
||||
if (rds_status & RDS_EVENT_PI_CODE) {
|
||||
ret = FMR_get_pi(0, &pi);
|
||||
if (!ret) {
|
||||
ret = FMR_get_rssi(g_idx, &rssi);
|
||||
if (rssi > FM_AF_THRESHOLD)
|
||||
g_CurrentRDS_PI = pi;
|
||||
}
|
||||
LOGE("get pi(0x%04x) \n", pi);
|
||||
}
|
||||
}
|
||||
return rds_status;
|
||||
}
|
||||
|
||||
jshort getPI(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
uint16_t pi = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_pi(g_idx, &pi);
|
||||
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
pi = -1; //there's some error happened
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
|
||||
jbyte getECC(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t ecc = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_ecc(g_idx, &ecc);
|
||||
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
ecc = -1; //there's some error happened
|
||||
}
|
||||
return ecc;
|
||||
}
|
||||
|
||||
jbyte getPTY(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t pty = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_pty(g_idx, &pty);
|
||||
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
pty = -1; //there's some error happened
|
||||
}
|
||||
return pty;
|
||||
}
|
||||
|
||||
jbyteArray getPs(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
jbyteArray PSname;
|
||||
uint8_t *ps = NULL;
|
||||
int ps_len = 0;
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_ps(g_idx, &ps, &ps_len);
|
||||
if (ret) {
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
return NULL;
|
||||
}
|
||||
PSname = env->NewByteArray(ps_len);
|
||||
env->SetByteArrayRegion(PSname, 0, ps_len, (const jbyte*)ps);
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return PSname;
|
||||
}
|
||||
|
||||
jbyteArray getLrText(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
jbyteArray LastRadioText;
|
||||
uint8_t *rt = NULL;
|
||||
int rt_len = 0;
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_rt(g_idx, &rt, &rt_len);
|
||||
if (ret) {
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
return NULL;
|
||||
}
|
||||
LastRadioText = env->NewByteArray(rt_len);
|
||||
env->SetByteArrayRegion(LastRadioText, 0, rt_len, (const jbyte*)rt);
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return LastRadioText;
|
||||
}
|
||||
|
||||
jshort activeAf(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
jshort ret_freq = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_active_af(g_idx, g_CurrentRDS_PI, (uint16_t*)&ret_freq);
|
||||
if (ret) {
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGD("%s, [ret=%d], ret_freq=%d\n", __func__, ret, ret_freq);
|
||||
return ret_freq;
|
||||
}
|
||||
|
||||
jshortArray getAFList(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
jshortArray AFList;
|
||||
char *af = NULL;
|
||||
int af_len = 0;
|
||||
UNUSED(thiz);
|
||||
|
||||
//ret = FMR_get_af(g_idx, &af, &af_len); // If need, we should implemate this API
|
||||
if (ret) {
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
return NULL;
|
||||
}
|
||||
AFList = env->NewShortArray(af_len);
|
||||
env->SetShortArrayRegion(AFList, 0, af_len, (const jshort*)af);
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return AFList;
|
||||
}
|
||||
|
||||
jshort activeTA(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
jshort ret_freq = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_active_ta(g_idx, (uint16_t*)&ret_freq);
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
return 0;
|
||||
}
|
||||
LOGD("%s, [ret=%d], ret_freq=%d\n", __func__, ret, ret_freq);
|
||||
return ret_freq;
|
||||
}
|
||||
|
||||
jshort deactiveTA(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
jshort ret_freq = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_deactive_ta(g_idx, (uint16_t*)&ret_freq);
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
return 0;
|
||||
}
|
||||
LOGD("%s, [ret=%d], ret_freq=%d\n", __func__, ret, ret_freq);
|
||||
return ret_freq;
|
||||
}
|
||||
|
||||
jint setRds(JNIEnv *env, jobject thiz, jboolean rdson)
|
||||
{
|
||||
int ret = 0;
|
||||
int onoff = -1;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
if (rdson == JNI_TRUE) {
|
||||
onoff = FMR_RDS_ON;
|
||||
} else {
|
||||
onoff = FMR_RDS_OFF;
|
||||
}
|
||||
ret = FMR_turn_on_off_rds(g_idx, onoff);
|
||||
if (ret) {
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGD("%s, [onoff=%d] [ret=%d]\n", __func__, onoff, ret);
|
||||
return ret?JNI_FALSE:JNI_TRUE;
|
||||
}
|
||||
|
||||
jboolean stopScan(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_stop_scan(g_idx);
|
||||
if (ret) {
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return ret?JNI_FALSE:JNI_TRUE;
|
||||
}
|
||||
|
||||
jint setMute(JNIEnv *env, jobject thiz, jboolean mute)
|
||||
{
|
||||
int ret = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_set_mute(g_idx, (int)mute);
|
||||
if (ret) {
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGD("%s, [mute=%d] [ret=%d]\n", __func__, (int)mute, ret);
|
||||
return ret?JNI_FALSE:JNI_TRUE;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Used to get chip ID.
|
||||
*Parameter:
|
||||
* None
|
||||
*Return value
|
||||
* 1000: chip AR1000
|
||||
* 6616: chip mt6616
|
||||
* -1: error
|
||||
******************************************/
|
||||
jint getchipid(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
int chipid = -1;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_chip_id(g_idx, &chipid);
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGD("%s, [chipid=%x] [ret=%d]\n", __func__, chipid, ret);
|
||||
return chipid;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Inquiry if RDS is support in driver.
|
||||
* Parameter:
|
||||
* None
|
||||
*Return Value:
|
||||
* 1: support
|
||||
* 0: NOT support
|
||||
* -1: error
|
||||
******************************************/
|
||||
jint isRdsSupport(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
int supt = -1;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_is_rdsrx_support(g_idx, &supt);
|
||||
if (ret) {
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGD("%s, [supt=%d] [ret=%d]\n", __func__, supt, ret);
|
||||
return supt;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Inquiry if FM is powered up.
|
||||
* Parameter:
|
||||
* None
|
||||
*Return Value:
|
||||
* 1: Powered up
|
||||
* 0: Did NOT powered up
|
||||
******************************************/
|
||||
jint isFMPoweredUp(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
int pwrup = -1;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_is_fm_pwrup(g_idx, &pwrup);
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGD("%s, [pwrup=%d] [ret=%d]\n", __func__, pwrup, ret);
|
||||
return pwrup;
|
||||
}
|
||||
/******************************************
|
||||
|
||||
* SwitchAntenna
|
||||
* Parameter:
|
||||
* antenna:
|
||||
0 : switch to long antenna
|
||||
1: switch to short antenna
|
||||
*Return Value:
|
||||
* 0: Success
|
||||
* 1: Failed
|
||||
* 2: Not support
|
||||
******************************************/
|
||||
jint switchAntenna(JNIEnv *env, jobject thiz, jint antenna)
|
||||
{
|
||||
int ret = 0;
|
||||
jint jret = 0;
|
||||
int ana = -1;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
if (0 == antenna) {
|
||||
ana = FM_LONG_ANA;
|
||||
} else if (1 == antenna) {
|
||||
ana = FM_SHORT_ANA;
|
||||
} else {
|
||||
LOGE("%s:fail, para error\n", __func__);
|
||||
jret = JNI_FALSE;
|
||||
goto out;
|
||||
}
|
||||
ret = FMR_ana_switch(g_idx, ana);
|
||||
if (ret == -ERR_UNSUPT_SHORTANA) {
|
||||
LOGW("Not support switchAntenna\n");
|
||||
jret = 2;
|
||||
} else if (ret) {
|
||||
LOGE("switchAntenna(), error\n");
|
||||
jret = 1;
|
||||
} else {
|
||||
jret = 0;
|
||||
}
|
||||
out:
|
||||
LOGD("%s: [antenna=%d] [ret=%d]\n", __func__, ana, ret);
|
||||
return jret;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Inquiry if FM is stereoMono.
|
||||
* Parameter:
|
||||
* None
|
||||
*Return Value:
|
||||
* JNI_TRUE: stereo
|
||||
* JNI_FALSE: mono
|
||||
******************************************/
|
||||
jboolean stereoMono(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
int stemono = -1;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_stereomono(g_idx, &stemono);
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGD("%s, [stemono=%d] [ret=%d]\n", __func__, stemono, ret);
|
||||
|
||||
return stemono?JNI_TRUE:JNI_FALSE;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Force set to stero/mono mode.
|
||||
* Parameter:
|
||||
* type: JNI_TRUE, mono; JNI_FALSE, stero
|
||||
*Return Value:
|
||||
* JNI_TRUE: success
|
||||
* JNI_FALSE: failed
|
||||
******************************************/
|
||||
jboolean setStereoMono(JNIEnv *env, jobject thiz, jboolean type)
|
||||
{
|
||||
int ret = 0;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_set_stereomono(g_idx, ((type == JNI_TRUE) ? 1 : 0));
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGD("%s,[ret=%d]\n", __func__, ret);
|
||||
|
||||
return (ret==0) ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Read cap array of short antenna.
|
||||
* Parameter:
|
||||
* None
|
||||
*Return Value:
|
||||
* CapArray
|
||||
******************************************/
|
||||
jshort readCapArray(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
int caparray = -1;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_caparray(g_idx, &caparray);
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
LOGD("%s, [caparray=%d] [ret=%d]\n", __func__, caparray, ret);
|
||||
|
||||
return (jshort)caparray;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Read cap array of short antenna.
|
||||
* Parameter:
|
||||
* None
|
||||
*Return Value:
|
||||
* CapArray : 0~100
|
||||
******************************************/
|
||||
jshort readRdsBler(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
int badratio = -1;
|
||||
UNUSED(env);
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_badratio(g_idx, &badratio);
|
||||
if(ret){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
}
|
||||
|
||||
if(badratio > 100){
|
||||
badratio = 100;
|
||||
LOGW("badratio value error, give a max value!");
|
||||
}else if(badratio < 0){
|
||||
badratio = 0;
|
||||
LOGW("badratio value error, give a min value!");
|
||||
}
|
||||
LOGD("%s, [badratio=%d] [ret=%d]\n", __func__, badratio, ret);
|
||||
|
||||
return (jshort)badratio;
|
||||
}
|
||||
|
||||
jintArray getHardwareVersion(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int ret = 0;
|
||||
jintArray hw_info;
|
||||
int *info = NULL;
|
||||
int info_len = 0;
|
||||
UNUSED(thiz);
|
||||
|
||||
ret = FMR_get_hw_info(g_idx, &info, &info_len);
|
||||
if(ret < 0){
|
||||
LOGE("%s, error, [ret=%d]\n", __func__, ret);
|
||||
return NULL;
|
||||
}
|
||||
hw_info = env->NewIntArray(info_len);
|
||||
env->SetIntArrayRegion(hw_info, 0, info_len, (const jint*)info);
|
||||
LOGD("%s, [ret=%d]\n", __func__, ret);
|
||||
return hw_info;
|
||||
}
|
||||
|
||||
static const char *classPathNameRx = "com/android/fmradio/FmNative";
|
||||
|
||||
static JNINativeMethod methodsRx[] = {
|
||||
{"openDev", "()Z", (void*)openDev},
|
||||
{"closeDev", "()Z", (void*)closeDev},
|
||||
{"powerUp", "(F)Z", (void*)powerUp},
|
||||
{"powerDown", "(I)Z", (void*)powerDown},
|
||||
{"tune", "(F)Z", (void*)tune},
|
||||
{"seek", "(FZ)F", (void*)seek},
|
||||
{"autoScan", "()[S", (void*)autoScan},
|
||||
{"stopScan", "()Z", (void*)stopScan},
|
||||
{"setRds", "(Z)I", (void*)setRds},
|
||||
{"readRds", "()S", (void*)readRds},
|
||||
{"getPs", "()[B", (void*)getPs},
|
||||
{"getLrText", "()[B", (void*)getLrText},
|
||||
{"activeAf", "()S", (void*)activeAf},
|
||||
{"setMute", "(Z)I", (void*)setMute},
|
||||
{"isRdsSupport", "()I", (void*)isRdsSupport},
|
||||
{"switchAntenna", "(I)I", (void*)switchAntenna},
|
||||
{"readRssi", "()I", (void*)readRssi},
|
||||
{"stereoMono", "()Z", (void*)stereoMono},
|
||||
{"setStereoMono", "(Z)Z", (void*)setStereoMono},
|
||||
{"readCapArray", "()S", (void*)readCapArray},
|
||||
{"readRdsBler", "()S", (void*)readRdsBler},
|
||||
{"emcmd","([S)[S",(void*)emcmd},
|
||||
{"emsetth","(II)Z",(void*)emsetth},
|
||||
{"getHardwareVersion", "()[I", (void*)getHardwareVersion},
|
||||
};
|
||||
|
||||
/*
|
||||
* Register several native methods for one class.
|
||||
*/
|
||||
static jint registerNativeMethods(JNIEnv* env, const char* className,
|
||||
JNINativeMethod* gMethods, int numMethods)
|
||||
{
|
||||
jclass clazz;
|
||||
|
||||
clazz = env->FindClass(className);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
}
|
||||
if (clazz == NULL) {
|
||||
LOGE("Native registration unable to find class '%s'", className);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
|
||||
LOGE("RegisterNatives failed for '%s'", className);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
LOGD("%s, success\n", __func__);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register native methods for all classes we know about.
|
||||
*
|
||||
* returns JNI_TRUE on success.
|
||||
*/
|
||||
static jint registerNatives(JNIEnv* env)
|
||||
{
|
||||
jint ret = JNI_FALSE;
|
||||
|
||||
if (registerNativeMethods(env, classPathNameRx,methodsRx,
|
||||
sizeof(methodsRx) / sizeof(methodsRx[0]))) {
|
||||
ret = JNI_TRUE;
|
||||
}
|
||||
|
||||
LOGD("%s, done\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* This is called by the VM when the shared library is first loaded.
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
JNIEnv* env;
|
||||
void* venv;
|
||||
} UnionJNIEnvToVoid;
|
||||
|
||||
jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
{
|
||||
UnionJNIEnvToVoid uenv;
|
||||
uenv.venv = NULL;
|
||||
jint result = -1;
|
||||
JNIEnv* env = NULL;
|
||||
UNUSED(reserved);
|
||||
|
||||
LOGI("JNI_OnLoad");
|
||||
|
||||
if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
|
||||
LOGE("ERROR: GetEnv failed");
|
||||
goto fail;
|
||||
}
|
||||
env = uenv.env;
|
||||
|
||||
if (registerNatives(env) != JNI_TRUE) {
|
||||
LOGE("ERROR: registerNatives failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((g_idx = FMR_init()) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
result = JNI_VERSION_1_4;
|
||||
|
||||
fail:
|
||||
return result;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue