universal7885: libfm-impl: Refactor

- Launch a sperate thread for polling (std::thread)
- Include logging about ioctl failures
This commit is contained in:
roynatech2544 2022-10-22 21:59:59 +09:00
commit a06a00d26b
5 changed files with 115 additions and 98 deletions

View file

@ -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"],
} }

View file

@ -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,49 +57,53 @@ 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,32 +115,28 @@ 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; LOG_IOCTL_ERR_ON_COND_NORETURN("VIDIOC_S_HW_FREQ_SEEK", ret < 0);
}
return FM_SUCCESS; return ret;
} }
static int channel_search(const int fd, unsigned int upward, static void channel_search(const int fd, unsigned int upward,
unsigned int wrap_around, unsigned int wrap_around, unsigned int spacing,
unsigned int spacing, int *channel) { int *channel) {
int ret; int ret;
ret = set_control(fd, V4L2_CID_S610_SEEK_MODE, ret = set_control(fd, V4L2_CID_S610_SEEK_MODE, FM_TUNER_AUTONOMOUS_SEARCH_MODE);
FM_TUNER_AUTONOMOUS_SEARCH_MODE);
if (ret < 0) LOG_IOCTL_ERR_ON_COND("V4L2_CID_S610_SEEK_MODE", ret < 0);
return ret;
ret = seek_frequency(fd, upward, wrap_around, spacing); ret = seek_frequency(fd, upward, wrap_around, spacing);
if (ret < 0) if (ret < 0) return;
return ret;
ret = get_frequency(fd, channel); ret = get_frequency(fd, channel);
if (ret < 0) if (ret < 0) return;
return ret;
return ret;
} }
/* /*
int next_channel(const int fd) { int next_channel(const int fd) {
int ret; int ret;
@ -125,20 +149,15 @@ int before_channel(const int fd) {
return ret; return ret;
} }
*/ */
int set_mute(const int fd, bool mute) {
void set_mute(const int fd, bool mute) {
int ret = set_control(fd, V4L2_CID_AUDIO_MUTE, !mute); int ret = set_control(fd, V4L2_CID_AUDIO_MUTE, !mute);
if (ret < 0) { LOG_IOCTL_ERR_ON_COND("V4L2_CID_AUDIO_MUTE", ret < 0);
return FM_FAILURE;
}
return FM_SUCCESS;
} }
int set_volume(int fd, int volume /* 1 ~ 15 */) { 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,8 +168,7 @@ 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);
} }
@ -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) {
}
if (!ret) {
return FM_FAILURE;
}
return FM_FAILURE - 1; return FM_FAILURE - 1;
}
return FM_FAILURE;
} }
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,25 +268,21 @@ 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) {
@ -289,4 +303,4 @@ 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

View file

@ -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;

View file

@ -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);