universal7885: fm-aidl: Move ioctl code to hal

This commit is contained in:
roynatech2544 2022-10-06 09:55:12 +00:00
commit 839dc3ae4c
8 changed files with 325 additions and 506 deletions

View file

@ -5,7 +5,6 @@ android_app {
],
platform_apis: true,
certificate: "platform",
jni_libs: ["libfmnative_jni"],
static_libs: [
"androidx.core_core",
"androidx.appcompat_appcompat",
@ -14,6 +13,7 @@ android_app {
"androidx.transition_transition",
"kotlinx_coroutines_android",
"androidx.coordinatorlayout_coordinatorlayout",
"vendor.eureka.hardware.fmradio-java",
],
required: [
"vendor.eureka.hardware.fmradio-service",

View file

@ -1,498 +0,0 @@
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <stdint.h>
#include <cstring>
#include <unistd.h>
#include <cerrno>
#include <iostream>
#include "s610_radio.h"
#include "v4l2_api.h"
#include <algorithm>
#include <jni.h>
#include <hardware/hardware.h>
#include <hidl/HidlSupport.h>
#include <hidl/LegacySupport.h>
#include <hidl/Status.h>
#include <vendor/eureka/hardware/fmradio/1.2/IFMRadio.h>
using android::sp;
using vendor::eureka::hardware::fmradio::V1_0::Direction;
using vendor::eureka::hardware::fmradio::V1_1::Status;
using vendor::eureka::hardware::fmradio::V1_2::IFMRadio;
// #define DEBUG
#define TRACK_SIZE 30
int64_t tracks[TRACK_SIZE] = {0};
bool FMThread = false;
int open_fm_device() {
int fd;
if ((fd = open("/dev/radio0", O_RDWR | O_CLOEXEC)) < 0) {
printf("Cannot open /dev/radio0.\n");
return -1;
}
return fd;
}
static int fm_radio_get_frequency(int fd, int64_t *channel) {
struct v4l2_frequency freq {};
int ret;
freq.tuner = 0;
freq.type = V4L2_TUNER_RADIO;
ret = ioctl(fd, VIDIOC_G_FREQUENCY, &freq);
if (ret < 0) {
printf("FmRadioController: failed to get frequency\n");
return FM_FAILURE;
}
*channel = (int64_t)freq.frequency / 16000;
return FM_SUCCESS;
}
static int fm_radio_set_frequency(int fd, int64_t channel) {
struct v4l2_frequency freq {};
int ret;
freq.tuner = 0;
freq.type = V4L2_TUNER_RADIO;
freq.frequency = (unsigned int)channel * 16000;
ret = ioctl(fd, VIDIOC_S_FREQUENCY, &freq);
if (ret < 0) {
printf("FmRadioController: failed to set frequency\n");
return FM_FAILURE;
}
return FM_SUCCESS;
}
static int fm_radio_set_control(int fd, unsigned int id, int64_t val) {
struct v4l2_control ctrl {};
int ret;
#ifdef DEBUG
printf("FmRadioController:fm_radio_set_control: id(%d) val(%ld)\n", id, val);
#endif
ctrl.id = id;
if (val)
ctrl.value = (unsigned int)val;
else
ctrl.value = 0;
ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
if (ret < 0) {
printf("FmRadioController: failed to set control\n");
return FM_FAILURE;
}
return FM_SUCCESS;
}
static int fm_radio_seek_frequency(int fd, unsigned int upward,
unsigned int wrap_around,
unsigned int spacing) {
struct v4l2_hw_freq_seek seek {};
int ret;
seek.tuner = 0;
seek.type = V4L2_TUNER_RADIO;
seek.seek_upward = upward;
seek.wrap_around = wrap_around;
seek.spacing = spacing;
ret = ioctl(fd, VIDIOC_S_HW_FREQ_SEEK, &seek);
if (ret < 0) {
printf("FmRadioController: failed to seek frequency\n");
return FM_FAILURE;
}
return FM_SUCCESS;
}
static int fm_radio_channel_searching(int fd, unsigned int upward,
unsigned int wrap_around,
unsigned int spacing, int64_t *channel) {
int ret;
ret = fm_radio_set_control(fd, V4L2_CID_S610_SEEK_MODE,
FM_TUNER_AUTONOMOUS_SEARCH_MODE);
if (ret < 0)
return ret;
ret = fm_radio_seek_frequency(fd, upward, wrap_around, spacing);
if (ret < 0)
return ret;
ret = fm_radio_get_frequency(fd, channel);
if (ret < 0)
return ret;
return ret;
}
static int fm_radio_set_tuner(int fd, unsigned int mode) {
struct v4l2_tuner tuner {};
int ret;
tuner.index = 0;
tuner.audmode = mode;
tuner.type = 1;
ret = ioctl(fd, VIDIOC_S_TUNER, &tuner);
if (ret < 0) {
printf("FmRadioController: failed to set tuner\n");
return FM_FAILURE;
}
return FM_SUCCESS;
}
static int fm_radio_get_tuner(int fd) {
struct v4l2_tuner tuner {};
int ret;
tuner.index = 0;
tuner.type = 1;
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
if (ret < 0) {
printf("FmRadioController: failed to set tuner\n");
return FM_FAILURE;
}
return tuner.audmode;
}
static int fm_radio_set_mute(int fd, bool mute) {
int muteint = 1;
if (mute)
muteint = 0;
int ret = fm_radio_set_control(fd, V4L2_CID_AUDIO_MUTE, muteint);
if (ret < 0) {
printf("FmRadioController: failed to set mute\n");
return FM_FAILURE;
}
return FM_SUCCESS;
}
static int fm_radio_set_volume(int fd, int volume /* 1 ~ 15 */) {
int ret = fm_radio_set_control(fd, V4L2_CID_AUDIO_VOLUME, volume);
if (ret < 0) {
printf("FmRadioController: failed to set volume\n");
return FM_FAILURE;
}
return FM_SUCCESS;
}
template <class C, typename T> bool contains(C &&c, T e) {
return std::find(std::begin(c), std::end(c), e) != std::end(c);
}
static int64_t fm_radio_get_freqs(int fd) {
int64_t ret = 0;
fm_radio_set_mute(fd, true);
sp<IFMRadio> service = IFMRadio::getService();
bool mSysfs = service->isAvailable() == Status::YES;
for (int64_t &track : tracks) {
if (mSysfs) {
service->adjustFreqByStep(Direction::UP);
ret = (int64_t)service->getFreqFromSysfs();
} else {
fm_radio_channel_searching(fd, 1, 0, FM_CHANNEL_SPACING_50KHZ, &ret);
}
if (contains(tracks, ret))
break;
track = ret;
// printf("Found Freq %ld\n", ret);
}
fm_radio_set_mute(fd, false);
return ret;
}
static int fm_radio_poll(int fd, struct pollfd *poll_fd) {
int ret;
poll_fd->fd = fd;
poll_fd->events = POLLIN;
poll_fd->revents = 0;
ret = poll(poll_fd, 1, 360);
if (ret > 0) {
if (poll_fd->revents & POLLIN) {
printf("FmRadioController: ready to read\n");
return FM_SUCCESS;
}
printf("FmRadioController: cannot read yet\n");
return FM_FAILURE;
}
if (!ret) {
printf("FmRadioController: polling timeout\n");
return FM_FAILURE;
}
printf("FmRadioController: pollig fail: %d\n", ret);
return FM_FAILURE - 1;
}
static int fm_radio_read(int fd, unsigned char *buf) {
int ret;
ret = read(fd, buf, FM_RADIO_RDS_DATA_MAX);
if (ret < 0) {
printf("FmRadioController: failed to read\n");
return FM_FAILURE;
}
return ret;
}
static int fm_radio_thread(int fd) {
struct pollfd radio_poll {};
unsigned char read_buf[FM_RADIO_RDS_DATA_MAX];
int ret;
while (FMThread) {
ret = fm_radio_poll(fd, &radio_poll);
if (ret < 0) {
if (ret < FM_FAILURE)
break;
else
continue;
}
ret = fm_radio_read(fd, read_buf);
if (ret < 0)
break;
}
return 0;
}
static unsigned int fm_radio_get_upperband_limit(int fd) {
int ret;
struct v4l2_tuner tuner {};
unsigned int freq;
tuner.index = 0;
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
if (ret < 0) {
return FM_FAILURE;
} else {
freq = (tuner.rangehigh / 16000);
return freq;
}
}
static unsigned int fm_radio_get_lowerband_limit(int fd) {
int ret;
unsigned int freq;
struct v4l2_tuner tuner {};
tuner.index = 0;
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
if (ret < 0) {
return FM_FAILURE;
} else {
freq = (tuner.rangelow / 16000);
return freq;
}
}
static int64_t fm_radio_get_rmssi(int fd) {
struct v4l2_tuner tuner {};
int ret;
int64_t rmssi;
tuner.index = 0;
tuner.signal = 0;
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
if (ret < 0) {
ret = FM_FAILURE;
} else {
rmssi = tuner.signal;
ret = rmssi;
}
return ret;
}
static int fm_radio_set_rssi(int fd, int64_t rssi) {
int ret = fm_radio_set_control(fd, V4L2_CID_S610_RSSI_TH, rssi);
if (ret < 0) {
return FM_FAILURE;
}
return FM_SUCCESS;
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_openFMDevice(
__unused JNIEnv *env, __unused jobject thiz) {
return open_fm_device();
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_getFMFreq(__unused JNIEnv *env,
__unused jobject thiz,
jint fd) {
int64_t freq;
fm_radio_get_frequency(fd, &freq);
return freq;
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_setFMFreq(__unused JNIEnv *env,
__unused jobject thiz,
jint fd, jint freq) {
return fm_radio_set_frequency(fd, freq);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_setFMVolume(__unused JNIEnv *env,
__unused jobject thiz,
jint fd,
jint volume) {
return fm_radio_set_volume(fd, volume);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_setFMMute(__unused JNIEnv *env,
__unused jobject thiz,
jint fd,
jboolean mute) {
return fm_radio_set_mute(fd, mute);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_getFmUpper(__unused JNIEnv *env,
__unused jobject thiz,
jint fd) {
return fm_radio_get_upperband_limit(fd);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_getFMLower(__unused JNIEnv *env,
__unused jobject thiz,
jint fd) {
return fm_radio_get_lowerband_limit(fd);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_getRMSSI(__unused JNIEnv *env,
__unused jobject thiz,
jint fd) {
return fm_radio_get_rmssi(fd);
}
extern "C" JNIEXPORT jlongArray JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_getFMTracks(JNIEnv *env,
__unused jobject thiz,
jint fd) {
fm_radio_get_freqs(fd);
jlongArray result;
result = (*env).NewLongArray(TRACK_SIZE);
if (result == nullptr) {
return nullptr; /* out of memory error thrown */
}
int i;
// fill a temp structure to use to populate the java int array
int64_t fill[TRACK_SIZE];
for (i = 0; i < TRACK_SIZE; i++) {
fill[i] =
tracks[i]; // put whatever logic you want to populate the values here.
}
// move from the temp structure to the java structure
(*env).SetLongArrayRegion(result, 0, TRACK_SIZE, fill);
return result;
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_setFMStereo(__unused JNIEnv *env,
__unused jobject thiz,
jint fd) {
return fm_radio_set_tuner(fd, 1);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_setFMMono(__unused JNIEnv *env,
__unused jobject thiz,
jint fd) {
return fm_radio_set_tuner(fd, 0);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_setFMThread(__unused JNIEnv *env,
__unused jobject thiz,
jint fd,
jboolean run) {
if (run) {
FMThread = true;
fm_radio_thread(fd);
} else {
FMThread = false;
}
return FM_SUCCESS;
}
extern "C" JNIEXPORT void JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_setFMBoot(__unused JNIEnv *env,
__unused jobject thiz,
jint fd) {
fm_radio_set_control(fd, V4L2_CID_S610_IF_COUNT1, 4800); // SetIFCount 1
fm_radio_set_control(fd, V4L2_CID_S610_IF_COUNT2, 5600); // SetIFCount 2
fm_radio_set_control(fd, V4L2_CID_S610_SOFT_STEREO_BLEND,
3172); // Set Soft Stereo Blend
fm_radio_set_control(fd, V4L2_CID_S610_SOFT_MUTE_COEFF,
16); // SetSoftMuteCoeff
fm_radio_set_control(fd, V4L2_CID_S610_CH_BAND,
S610_BAND_FM); // Set Band (To FM)
fm_radio_set_control(fd, V4L2_CID_S610_CH_SPACING,
FM_CHANNEL_SPACING_50KHZ); // Spacing 5kHz
fm_radio_set_control(fd, V4L2_CID_S610_RDS_ON, FM_RDS_ENABLE); // RDS on
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_getNextChannel(
__unused JNIEnv *env, __unused jobject thiz, jint fd) {
int64_t ret;
sp<IFMRadio> service = IFMRadio::getService();
bool mSysfs = service->isAvailable() == Status::YES;
if (!mSysfs) {
fm_radio_channel_searching(fd, 1, 0, FM_CHANNEL_SPACING_100KHZ, &ret);
} else {
service->adjustFreqByStep(Direction::UP);
ret = service->getFreqFromSysfs();
}
return ret;
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_getBeforeChannel(
__unused JNIEnv *env, __unused jobject thiz, jint fd) {
int64_t ret;
sp<IFMRadio> service = IFMRadio::getService();
bool mSysfs = service->isAvailable() == Status::YES;
if (!mSysfs) {
fm_radio_channel_searching(fd, 0, 0, FM_CHANNEL_SPACING_100KHZ, &ret);
} else {
service->adjustFreqByStep(Direction::DOWN);
ret = service->getFreqFromSysfs();
}
return ret;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_getAudioChannel(
__unused JNIEnv *env, __unused jobject thiz, jint fd) {
int channel = fm_radio_get_tuner(fd);
if (channel == V4L2_TUNER_MODE_STEREO) {
return true; // Is EarPhones
} else {
return false; // Is Speaker
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_stopSearching(
__unused JNIEnv *env, __unused jobject thiz, jint fd) {
fm_radio_set_control(fd, V4L2_CID_S610_SEEK_CANCEL, 1);
}
extern "C" JNIEXPORT jint JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_setFMRSSI(__unused JNIEnv *env,
__unused jobject thiz,
jint fd, jint rssi) {
return fm_radio_set_rssi(fd, rssi);
}
extern "C" JNIEXPORT void JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_closeFMDevice(
__unused JNIEnv *env, __unused jobject thiz, jint fd) {
close(fd);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_eurekateam_fmradio_NativeFMInterface_getSysfsSupport(
__unused JNIEnv *env, __unused jobject thiz) {
sp<IFMRadio> service = IFMRadio::getService();
return service->isAvailable() == Status::YES;
}

View file

@ -1,20 +1,18 @@
cc_library_shared {
name: "libfmnative_jni",
cc_library_static {
name: "libfm_slsi-impl",
cflags: [
"-Wno-unused-parameter",
],
srcs: [
"fm_ioctl.cpp",
"fm_route.cpp",
"FM_Device_ctl.cpp",
"FM_AudioRoute_ctl.cpp",
],
export_include_dirs: ["public"],
defaults: ["eureka_defaults"],
shared_libs: [
"libhidlbase",
"liblog",
"libutils",
"vendor.eureka.hardware.fmradio@1.0",
"vendor.eureka.hardware.fmradio@1.1",
"vendor.eureka.hardware.fmradio@1.2",
"audioflinger-aidl-cpp",
"audiopolicy-aidl-cpp",
"audiopolicy-types-aidl-cpp",

View file

@ -20,6 +20,7 @@
#define FM_FAILURE (-1)
#define FM_SUCCESS 0
#define IOHANDLE 13
using namespace android;
extern "C" JNIEXPORT jboolean JNICALL

View file

@ -0,0 +1,293 @@
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <stdint.h>
#include <cstring>
#include <unistd.h>
#include <cerrno>
#include <iostream>
#include "S610_FMRadio.h"
#include "V4L2_4_4_API.h"
#include <algorithm>
#include <jni.h>
#include <memory>
#include <vector>
#include <thread>
namespace fm_radio_slsi {
constexpr const int TRACK_SIZE = 30;
static bool FMThread = false;
int open_device(void) {
int fd;
if ((fd = open("/dev/radio0", O_RDWR | O_CLOEXEC)) < 0) {
printf("Cannot open /dev/radio0.\n");
return -1;
}
return fd;
}
int get_frequency(const int fd, int64_t *channel) {
struct v4l2_frequency freq {};
int ret;
freq.tuner = 0;
freq.type = V4L2_TUNER_RADIO;
ret = ioctl(fd, VIDIOC_G_FREQUENCY, &freq);
if (ret < 0)
return FM_FAILURE;
*channel = static_cast<int64_t>(freq.frequency) / 16000;
return FM_SUCCESS;
}
int set_frequency(const int fd, int64_t channel) {
struct v4l2_frequency freq {};
int ret;
freq.tuner = 0;
freq.type = V4L2_TUNER_RADIO;
freq.frequency = (unsigned int)channel * 16000;
ret = ioctl(fd, VIDIOC_S_FREQUENCY, &freq);
if (ret < 0) {
printf("FmRadioController: failed to set frequency\n");
return FM_FAILURE;
}
return FM_SUCCESS;
}
static int set_control(const int fd, unsigned int id, int64_t val) {
struct v4l2_control ctrl {};
int ret;
ctrl.id = id;
if (val)
ctrl.value = static_cast<unsigned int>(val);
else
ctrl.value = 0;
ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
if (ret < 0) {
return FM_FAILURE;
}
return FM_SUCCESS;
}
int seek_frequency(int fd, unsigned int upward,
unsigned int wrap_around,
unsigned int spacing) {
struct v4l2_hw_freq_seek seek {};
int ret;
seek.tuner = 0;
seek.type = V4L2_TUNER_RADIO;
seek.seek_upward = upward;
seek.wrap_around = wrap_around;
seek.spacing = spacing;
ret = ioctl(fd, VIDIOC_S_HW_FREQ_SEEK, &seek);
if (ret < 0) {
return FM_FAILURE;
}
return FM_SUCCESS;
}
int channel_search(const int fd, unsigned int upward,
unsigned int wrap_around,
unsigned int spacing, int64_t *channel) {
int ret;
ret = set_control(fd, V4L2_CID_S610_SEEK_MODE,
FM_TUNER_AUTONOMOUS_SEARCH_MODE);
if (ret < 0)
return ret;
ret = seek_frequency(fd, upward, wrap_around, spacing);
if (ret < 0)
return ret;
ret = get_frequency(fd, channel);
if (ret < 0)
return ret;
return ret;
}
int set_mute(const int fd, bool mute) {
int ret = set_control(fd, V4L2_CID_AUDIO_MUTE, !mute);
if (ret < 0) {
return FM_FAILURE;
}
return FM_SUCCESS;
}
int set_volume(int fd, int volume /* 1 ~ 15 */) {
int ret = set_control(fd, V4L2_CID_AUDIO_VOLUME, volume);
if (ret < 0) {
return FM_FAILURE;
}
return FM_SUCCESS;
}
std::unique_ptr<int64_t[]> get_freqs(const int fd) {
set_mute(fd, true);
auto map = std::vector<int64_t>();
for (int i = 0; i < TRACK_SIZE; i++) {
int64_t found = 0;
channel_search(fd, 1, 0, FM_CHANNEL_SPACING_50KHZ, &found);
for (auto k : map) {
if (k == found)
continue;
}
map.push_back(found);
}
auto ptr = std::make_unique<int64_t[]>(map.size());
for (unsigned long i = 0; i < map.size(); i++) {
ptr[i] = map[i];
}
set_mute(fd, false);
return std::move(ptr);
}
static int fm_poll(int fd, struct pollfd *poll_fd) {
int ret;
poll_fd->fd = fd;
poll_fd->events = POLLIN;
poll_fd->revents = 0;
ret = poll(poll_fd, 1, 360);
if (ret > 0) {
if (poll_fd->revents & POLLIN) {
return FM_SUCCESS;
}
return FM_FAILURE;
}
if (!ret) {
return FM_FAILURE;
}
return FM_FAILURE - 1;
}
static int fm_read(int fd, unsigned char *buf) {
int ret;
ret = read(fd, buf, FM_RADIO_RDS_DATA_MAX);
if (ret < 0) {
printf("FmRadioController: failed to read\n");
return FM_FAILURE;
}
return ret;
}
static void fm_thread(int fd) {
struct pollfd radio_poll {};
unsigned char read_buf[FM_RADIO_RDS_DATA_MAX];
int ret;
while (FMThread) {
ret = fm_poll(fd, &radio_poll);
if (ret < 0) {
if (ret < FM_FAILURE)
break;
else
continue;
}
ret = fm_read(fd, read_buf);
if (ret < 0)
break;
}
}
void fm_thread_set(const int fd, const bool enable) {
FMThread = enable;
if (enable) fm_thread(fd);
}
unsigned int get_upperband_limit(int fd) {
int ret;
struct v4l2_tuner tuner {};
unsigned int freq;
tuner.index = 0;
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
if (ret < 0) {
return FM_FAILURE;
} else {
freq = (tuner.rangehigh / 16000);
return freq;
}
}
unsigned int get_lowerband_limit(int fd) {
int ret;
unsigned int freq;
struct v4l2_tuner tuner {};
tuner.index = 0;
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
if (ret < 0) {
return FM_FAILURE;
} else {
freq = (tuner.rangelow / 16000);
return freq;
}
}
int64_t get_rmssi(int fd) {
struct v4l2_tuner tuner {};
int ret;
int64_t rmssi;
tuner.index = 0;
tuner.signal = 0;
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
if (ret < 0) {
ret = FM_FAILURE;
} else {
rmssi = tuner.signal;
ret = rmssi;
}
return ret;
}
int set_rssi(int fd, int64_t rssi) {
int ret = set_control(fd, V4L2_CID_S610_RSSI_TH, rssi);
if (ret < 0) {
return FM_FAILURE;
}
return FM_SUCCESS;
}
void bootctrl(const int fd) {
set_control(fd, V4L2_CID_S610_IF_COUNT1, 4800); // SetIFCount 1
set_control(fd, V4L2_CID_S610_IF_COUNT2, 5600); // SetIFCount 2
set_control(fd, V4L2_CID_S610_SOFT_STEREO_BLEND,
3172); // Set Soft Stereo Blend
set_control(fd, V4L2_CID_S610_SOFT_MUTE_COEFF,
16); // SetSoftMuteCoeff
set_control(fd, V4L2_CID_S610_CH_BAND,
S610_BAND_FM); // Set Band (To FM)
set_control(fd, V4L2_CID_S610_CH_SPACING,
FM_CHANNEL_SPACING_50KHZ); // Spacing 5kHz
set_control(fd, V4L2_CID_S610_RDS_ON, FM_RDS_ENABLE); // RDS on
}
void stop_search(const int fd) {
set_control(fd, V4L2_CID_S610_SEEK_CANCEL, 1);
}
}

View file

@ -1,3 +1,4 @@
#include <cstdint>
typedef u_int8_t __u8;
typedef int32_t __s32;

View file

@ -0,0 +1,24 @@
#pragma once
#include <memory>
namespace fm_radio_slsi {
int open_device(void);
int get_frequency(const int fd, int64_t *channel);
int set_frequency(const int fd, int64_t channel);
int seek_frequency(int fd, unsigned int upward, unsigned int wrap_around,
unsigned int spacing);
int channel_search(const int fd, unsigned int upward, unsigned int wrap_around,
unsigned int spacing, int64_t *channel);
int set_mute(const int fd, bool mute);
int set_volume(int fd, int volume);
std::unique_ptr<int64_t[]> get_freqs(const int fd);
void fm_thread_set(const int fd, const bool enable);
unsigned int get_upperband_limit(int fd);
unsigned int get_lowerband_limit(int fd);
int64_t get_rmssi(int fd);
int set_rssi(int fd, int64_t rssi);
void bootctrl(const int fd);
void stop_search(const int fd);
} // namespace fm_radio_slsi