mirror of
https://github.com/chararomandroid/android_device_samsung_a20
synced 2026-08-21 11:55:31 -04:00
universal7885: libfm-impl: Refactor
- Launch a sperate thread for polling (std::thread) - Include logging about ioctl failures
This commit is contained in:
parent
dd4e9fb547
commit
a06a00d26b
5 changed files with 115 additions and 98 deletions
|
|
@ -4,11 +4,13 @@ cc_library_static {
|
||||||
"-Wno-unused-parameter",
|
"-Wno-unused-parameter",
|
||||||
],
|
],
|
||||||
srcs: [
|
srcs: [
|
||||||
"FM_Device_ctl.cpp",
|
"FMDeviceControl.cpp",
|
||||||
],
|
],
|
||||||
|
shared_libs: ["libbase"],
|
||||||
export_include_dirs: ["public"],
|
export_include_dirs: ["public"],
|
||||||
defaults: [
|
defaults: [
|
||||||
"eureka_defaults",
|
"eureka_defaults",
|
||||||
"fm_aidl_defaults",
|
"fm_aidl_defaults"
|
||||||
],
|
],
|
||||||
|
header_libs: ["logformat"],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,51 @@
|
||||||
|
#include <LogFormat.h>
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <cstring>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <iostream>
|
#include <cstring>
|
||||||
#include "S610_FMRadio.h"
|
#include <thread>
|
||||||
#include "V4L2_4_4_API.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Radio_S610.h"
|
||||||
|
#include "V4L2_API.h"
|
||||||
|
|
||||||
namespace fm_radio_slsi {
|
namespace fm_radio_slsi {
|
||||||
|
|
||||||
static bool FMThread = false;
|
static bool FMThread = false;
|
||||||
|
|
||||||
|
constexpr const char *FM_DEV_PATH = "/dev/radio0";
|
||||||
|
|
||||||
|
#define LOG_IOCTL_ERR(cmd) \
|
||||||
|
LOG(ERROR) << make_str(std::string("Failed to call" cmd "ioctl(), %d (%s)"), \
|
||||||
|
errno, strerror(-errno))
|
||||||
|
|
||||||
|
#define LOG_IOCTL_ERR_ON_COND_NORETURN(cmd, cond) \
|
||||||
|
({ \
|
||||||
|
if ((cond)) { \
|
||||||
|
LOG_IOCTL_ERR(cmd); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define LOG_IOCTL_ERR_ON_COND(cmd, cond) \
|
||||||
|
({ \
|
||||||
|
if ((cond)) { \
|
||||||
|
LOG_IOCTL_ERR(cmd); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
int open_device(void) {
|
int open_device(void) {
|
||||||
int fd;
|
int fd;
|
||||||
if ((fd = open("/dev/radio0", O_RDWR | O_CLOEXEC)) < 0) {
|
if ((fd = open(FM_DEV_PATH, O_RDWR | O_CLOEXEC)) < 0) {
|
||||||
printf("Cannot open /dev/radio0.\n");
|
LOG(ERROR) << make_str("Failed to open %s, %d (%s)", FM_DEV_PATH, errno,
|
||||||
|
strerror(-errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
LOG(DEBUG) << make_str("Opened %s, fd %d", FM_DEV_PATH, fd);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,50 +57,54 @@ int get_frequency(const int fd, int *channel) {
|
||||||
freq.type = V4L2_TUNER_RADIO;
|
freq.type = V4L2_TUNER_RADIO;
|
||||||
|
|
||||||
ret = ioctl(fd, VIDIOC_G_FREQUENCY, &freq);
|
ret = ioctl(fd, VIDIOC_G_FREQUENCY, &freq);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
return FM_FAILURE;
|
LOG_IOCTL_ERR("VIDIOC_G_FREQUENCY");
|
||||||
|
*channel = FM_FAILURE;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
*channel = static_cast<int>(freq.frequency) / 16000;
|
*channel = static_cast<int>(freq.frequency) / 16000;
|
||||||
|
|
||||||
return FM_SUCCESS;
|
LOG(DEBUG) << make_str("Channel freq: %d", *channel);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_frequency(const int fd, int channel) {
|
void set_frequency(const int fd, int channel) {
|
||||||
struct v4l2_frequency freq {};
|
struct v4l2_frequency freq {};
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
LOG(DEBUG) << make_str("Channel freq: %d", channel);
|
||||||
|
|
||||||
freq.tuner = 0;
|
freq.tuner = 0;
|
||||||
freq.type = V4L2_TUNER_RADIO;
|
freq.type = V4L2_TUNER_RADIO;
|
||||||
freq.frequency = (unsigned int)channel * 16000;
|
freq.frequency = (unsigned int)channel * 16000;
|
||||||
|
|
||||||
ret = ioctl(fd, VIDIOC_S_FREQUENCY, &freq);
|
ret = ioctl(fd, VIDIOC_S_FREQUENCY, &freq);
|
||||||
if (ret < 0) {
|
|
||||||
printf("FmRadioController: failed to set frequency\n");
|
|
||||||
return FM_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FM_SUCCESS;
|
LOG_IOCTL_ERR_ON_COND("VIDIOC_S_FREQUENCY", ret < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_control(const int fd, unsigned int id, int val) {
|
static int set_control(const int fd, unsigned int id, int val) {
|
||||||
struct v4l2_control ctrl {};
|
struct v4l2_control ctrl {};
|
||||||
int ret;
|
int ret;
|
||||||
ctrl.id = id;
|
ctrl.id = id;
|
||||||
|
|
||||||
|
LOG(DEBUG) << make_str("Control value: %d", val);
|
||||||
|
|
||||||
if (val)
|
if (val)
|
||||||
ctrl.value = static_cast<unsigned int>(val);
|
ctrl.value = static_cast<unsigned int>(val);
|
||||||
else
|
else
|
||||||
ctrl.value = 0;
|
ctrl.value = 0;
|
||||||
|
|
||||||
ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
|
ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
|
||||||
if (ret < 0) {
|
|
||||||
return FM_FAILURE;
|
LOG_IOCTL_ERR_ON_COND_NORETURN("VIDIOC_S_CTRL", ret < 0);
|
||||||
}
|
|
||||||
return FM_SUCCESS;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int seek_frequency(int fd, unsigned int upward,
|
static int seek_frequency(int fd, unsigned int upward, unsigned int wrap_around,
|
||||||
unsigned int wrap_around,
|
unsigned int spacing) {
|
||||||
unsigned int spacing) {
|
|
||||||
struct v4l2_hw_freq_seek seek {};
|
struct v4l2_hw_freq_seek seek {};
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
@ -87,58 +115,49 @@ static int seek_frequency(int fd, unsigned int upward,
|
||||||
seek.spacing = spacing;
|
seek.spacing = spacing;
|
||||||
|
|
||||||
ret = ioctl(fd, VIDIOC_S_HW_FREQ_SEEK, &seek);
|
ret = ioctl(fd, VIDIOC_S_HW_FREQ_SEEK, &seek);
|
||||||
if (ret < 0) {
|
|
||||||
return FM_FAILURE;
|
|
||||||
}
|
|
||||||
return FM_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int channel_search(const int fd, unsigned int upward,
|
LOG_IOCTL_ERR_ON_COND_NORETURN("VIDIOC_S_HW_FREQ_SEEK", ret < 0);
|
||||||
unsigned int wrap_around,
|
|
||||||
unsigned int spacing, int *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;
|
return ret;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
int next_channel(const int fd) {
|
static void channel_search(const int fd, unsigned int upward,
|
||||||
int ret;
|
unsigned int wrap_around, unsigned int spacing,
|
||||||
channel_search(fd, 1, 0, FM_CHANNEL_SPACING_100KHZ, &ret);
|
int *channel) {
|
||||||
return ret;
|
int ret;
|
||||||
}
|
|
||||||
int before_channel(const int fd) {
|
ret = set_control(fd, V4L2_CID_S610_SEEK_MODE, FM_TUNER_AUTONOMOUS_SEARCH_MODE);
|
||||||
int ret;
|
|
||||||
channel_search(fd, 0, 0, FM_CHANNEL_SPACING_100KHZ, &ret);
|
LOG_IOCTL_ERR_ON_COND("V4L2_CID_S610_SEEK_MODE", ret < 0);
|
||||||
return ret;
|
|
||||||
}
|
ret = seek_frequency(fd, upward, wrap_around, spacing);
|
||||||
*/
|
if (ret < 0) return;
|
||||||
int set_mute(const int fd, bool mute) {
|
|
||||||
int ret = set_control(fd, V4L2_CID_AUDIO_MUTE, !mute);
|
ret = get_frequency(fd, channel);
|
||||||
if (ret < 0) {
|
if (ret < 0) return;
|
||||||
return FM_FAILURE;
|
|
||||||
}
|
|
||||||
return FM_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_volume(int fd, int volume /* 1 ~ 15 */) {
|
/*
|
||||||
|
int next_channel(const int fd) {
|
||||||
|
int ret;
|
||||||
|
channel_search(fd, 1, 0, FM_CHANNEL_SPACING_100KHZ, &ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
int before_channel(const int fd) {
|
||||||
|
int ret;
|
||||||
|
channel_search(fd, 0, 0, FM_CHANNEL_SPACING_100KHZ, &ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void set_mute(const int fd, bool mute) {
|
||||||
|
int ret = set_control(fd, V4L2_CID_AUDIO_MUTE, !mute);
|
||||||
|
LOG_IOCTL_ERR_ON_COND("V4L2_CID_AUDIO_MUTE", ret < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_volume(int fd, int volume /* 1 ~ 15 */) {
|
||||||
int ret = set_control(fd, V4L2_CID_AUDIO_VOLUME, volume);
|
int ret = set_control(fd, V4L2_CID_AUDIO_VOLUME, volume);
|
||||||
if (ret < 0) {
|
LOG_IOCTL_ERR_ON_COND("V4L2_CID_AUDIO_VOLUME", ret < 0);
|
||||||
return FM_FAILURE;
|
|
||||||
}
|
|
||||||
return FM_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> get_freqs(const int fd) {
|
std::vector<int> get_freqs(const int fd) {
|
||||||
|
|
@ -149,10 +168,9 @@ std::vector<int> get_freqs(const int fd) {
|
||||||
int found = 0;
|
int found = 0;
|
||||||
channel_search(fd, 1, 0, FM_CHANNEL_SPACING_50KHZ, &found);
|
channel_search(fd, 1, 0, FM_CHANNEL_SPACING_50KHZ, &found);
|
||||||
for (auto k : map) {
|
for (auto k : map) {
|
||||||
if (k == found)
|
if (k == found) continue;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
map.push_back(found);
|
map.push_back(found);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_mute(fd, false);
|
set_mute(fd, false);
|
||||||
|
|
@ -171,22 +189,18 @@ static int fm_poll(int fd, struct pollfd *poll_fd) {
|
||||||
if (poll_fd->revents & POLLIN) {
|
if (poll_fd->revents & POLLIN) {
|
||||||
return FM_SUCCESS;
|
return FM_SUCCESS;
|
||||||
}
|
}
|
||||||
return FM_FAILURE;
|
} else if (ret < 0) {
|
||||||
|
return FM_FAILURE - 1;
|
||||||
}
|
}
|
||||||
|
return FM_FAILURE;
|
||||||
if (!ret) {
|
|
||||||
return FM_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FM_FAILURE - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fm_read(int fd, unsigned char *buf) {
|
static int fm_read(int fd, unsigned char *buf) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = read(fd, buf, FM_RADIO_RDS_DATA_MAX);
|
ret = read(fd, buf, FM_RADIO_RDS_DATA_MAX);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printf("FmRadioController: failed to read\n");
|
|
||||||
return FM_FAILURE;
|
return FM_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,14 +222,16 @@ static void fm_thread(int fd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fm_read(fd, read_buf);
|
ret = fm_read(fd, read_buf);
|
||||||
if (ret < 0)
|
if (ret < 0) break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fm_thread_set(const int fd, const bool enable) {
|
void fm_thread_set(const int fd, const bool enable) {
|
||||||
FMThread = enable;
|
FMThread = enable;
|
||||||
if (enable) fm_thread(fd);
|
if (enable) {
|
||||||
|
std::thread thread = std::thread(fm_thread, fd);
|
||||||
|
thread.detach();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int get_upperband_limit(int fd) {
|
unsigned int get_upperband_limit(int fd) {
|
||||||
|
|
@ -225,6 +241,7 @@ unsigned int get_upperband_limit(int fd) {
|
||||||
tuner.index = 0;
|
tuner.index = 0;
|
||||||
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
|
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
LOG_IOCTL_ERR("VIDIOC_G_TUNER");
|
||||||
return FM_FAILURE;
|
return FM_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
freq = (tuner.rangehigh / 16000);
|
freq = (tuner.rangehigh / 16000);
|
||||||
|
|
@ -240,6 +257,7 @@ unsigned int get_lowerband_limit(int fd) {
|
||||||
tuner.index = 0;
|
tuner.index = 0;
|
||||||
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
|
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
LOG_IOCTL_ERR("VIDIOC_G_TUNER");
|
||||||
return FM_FAILURE;
|
return FM_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
freq = (tuner.rangelow / 16000);
|
freq = (tuner.rangelow / 16000);
|
||||||
|
|
@ -250,43 +268,39 @@ unsigned int get_lowerband_limit(int fd) {
|
||||||
int get_rmssi(int fd) {
|
int get_rmssi(int fd) {
|
||||||
struct v4l2_tuner tuner {};
|
struct v4l2_tuner tuner {};
|
||||||
int ret;
|
int ret;
|
||||||
int rmssi;
|
|
||||||
tuner.index = 0;
|
tuner.index = 0;
|
||||||
tuner.signal = 0;
|
tuner.signal = 0;
|
||||||
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
|
ret = ioctl(fd, VIDIOC_G_TUNER, &tuner);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
LOG_IOCTL_ERR("VIDIOC_G_TUNER");
|
||||||
ret = FM_FAILURE;
|
ret = FM_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
rmssi = tuner.signal;
|
ret = tuner.signal;
|
||||||
ret = rmssi;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_rssi(int fd, int rssi) {
|
void set_rssi(int fd, int rssi) {
|
||||||
int ret = set_control(fd, V4L2_CID_S610_RSSI_TH, rssi);
|
int ret = set_control(fd, V4L2_CID_S610_RSSI_TH, rssi);
|
||||||
if (ret < 0) {
|
LOG_IOCTL_ERR_ON_COND("V4L2_CID_S610_RSSI_TH", ret < 0);
|
||||||
return FM_FAILURE;
|
|
||||||
}
|
|
||||||
return FM_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bootctrl(const int fd) {
|
void bootctrl(const int fd) {
|
||||||
set_control(fd, V4L2_CID_S610_IF_COUNT1, 4800); // SetIFCount 1
|
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_IF_COUNT2, 5600); // SetIFCount 2
|
||||||
set_control(fd, V4L2_CID_S610_SOFT_STEREO_BLEND,
|
set_control(fd, V4L2_CID_S610_SOFT_STEREO_BLEND,
|
||||||
3172); // Set Soft Stereo Blend
|
3172); // Set Soft Stereo Blend
|
||||||
set_control(fd, V4L2_CID_S610_SOFT_MUTE_COEFF,
|
set_control(fd, V4L2_CID_S610_SOFT_MUTE_COEFF,
|
||||||
16); // SetSoftMuteCoeff
|
16); // SetSoftMuteCoeff
|
||||||
set_control(fd, V4L2_CID_S610_CH_BAND,
|
set_control(fd, V4L2_CID_S610_CH_BAND,
|
||||||
S610_BAND_FM); // Set Band (To FM)
|
S610_BAND_FM); // Set Band (To FM)
|
||||||
set_control(fd, V4L2_CID_S610_CH_SPACING,
|
set_control(fd, V4L2_CID_S610_CH_SPACING,
|
||||||
FM_CHANNEL_SPACING_50KHZ); // Spacing 5kHz
|
FM_CHANNEL_SPACING_50KHZ); // Spacing 5kHz
|
||||||
set_control(fd, V4L2_CID_S610_RDS_ON, FM_RDS_ENABLE); // RDS on
|
set_control(fd, V4L2_CID_S610_RDS_ON, FM_RDS_ENABLE); // RDS on
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_search(const int fd) {
|
void stop_search(const int fd) {
|
||||||
set_control(fd, V4L2_CID_S610_SEEK_CANCEL, 1);
|
set_control(fd, V4L2_CID_S610_SEEK_CANCEL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace fm_radio_slsi
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
typedef u_int8_t __u8;
|
typedef uint8_t __u8;
|
||||||
typedef int32_t __s32;
|
typedef int32_t __s32;
|
||||||
typedef u_int32_t __u32;
|
typedef uint32_t __u32;
|
||||||
|
|
||||||
struct v4l2_tuner {
|
struct v4l2_tuner {
|
||||||
__u32 index;
|
__u32 index;
|
||||||
|
|
@ -6,17 +6,17 @@ namespace fm_radio_slsi {
|
||||||
|
|
||||||
int open_device(void);
|
int open_device(void);
|
||||||
int get_frequency(const int fd, int *channel);
|
int get_frequency(const int fd, int *channel);
|
||||||
int set_frequency(const int fd, int channel);
|
void set_frequency(const int fd, int channel);
|
||||||
//int next_channel(const int fd);
|
//int next_channel(const int fd);
|
||||||
//int before_channel(const int fd);
|
//int before_channel(const int fd);
|
||||||
int set_mute(const int fd, bool mute);
|
void set_mute(const int fd, bool mute);
|
||||||
int set_volume(int fd, int volume);
|
void set_volume(int fd, int volume);
|
||||||
std::vector<int> get_freqs(const int fd);
|
std::vector<int> get_freqs(const int fd);
|
||||||
void fm_thread_set(const int fd, const bool enable);
|
void fm_thread_set(const int fd, const bool enable);
|
||||||
unsigned int get_upperband_limit(int fd);
|
unsigned int get_upperband_limit(int fd);
|
||||||
unsigned int get_lowerband_limit(int fd);
|
unsigned int get_lowerband_limit(int fd);
|
||||||
int64_t get_rmssi(int fd);
|
int get_rmssi(int fd);
|
||||||
int set_rssi(int fd, int rssi);
|
void set_rssi(int fd, int rssi);
|
||||||
void bootctrl(const int fd);
|
void bootctrl(const int fd);
|
||||||
void stop_search(const int fd);
|
void stop_search(const int fd);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue