1
0
mirror of https://github.com/danog/libdvb.git synced 2024-11-26 20:04:39 +01:00
This commit is contained in:
Daniil Gentili 2022-03-18 21:49:42 +01:00
parent 58c1693337
commit 5b70f19bd0
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
4 changed files with 133 additions and 178 deletions

View File

@ -1,6 +1,4 @@
use itertools::Itertools;
use crate::{dtv_property, get_dtv_property};
use crate::{dtv_property, req_dtv_properties};
mod status;
pub mod sys;
@ -141,24 +139,17 @@ impl FeDevice {
self.caps = feinfo.caps;
// DVB v5 properties
let mut cmdseq = [
dtv_property!(DTV_API_VERSION, 0),
dtv_property!(DTV_ENUM_DELSYS, DtvPropertyBuffer::default()),
];
self.get_properties(&mut cmdseq).context("FE: get api version (deprecated driver)")?;
let (api_version, enum_delsys) = req_dtv_properties!(
self,
DTV_API_VERSION,
DTV_ENUM_DELSYS
).context("FE: get api version (deprecated driver)")?;
// DVB API Version
self.api_version = get_dtv_property!(cmdseq[0], DTV_API_VERSION).context("FE: get api version")? as u16;
self.api_version = api_version as u16;
// Suppoerted delivery systems
self.delivery_system_list = get_dtv_property!(cmdseq[1], DTV_ENUM_DELSYS).context("FE: get delivery systems")?
.into_iter()
.cloned()
.map_into::<u32>()
.map(fe_delivery_system::from_repr)
.collect::<Option<_>>()
.context("Invalid")?;
self.delivery_system_list = enum_delsys;
// dev-file metadata
@ -218,19 +209,19 @@ impl FeDevice {
fn check_properties(&self, cmdseq: &[DtvProperty]) -> Result<()> {
for p in cmdseq {
match p {
DTV_FREQUENCY(DtvPropertyData{data, ..}) => {
DTV_FREQUENCY(DtvPropertyRequest{data, ..}) => {
ensure!(
self.frequency_range.contains(&data),
"FE: frequency out of range"
);
}
DTV_SYMBOL_RATE(DtvPropertyData{data, ..}) => {
DTV_SYMBOL_RATE(DtvPropertyRequest{data, ..}) => {
ensure!(
self.symbolrate_range.contains(&data),
"FE: symbolrate out of range"
);
}
DTV_INVERSION(DtvPropertyData{data, ..}) => {
DTV_INVERSION(DtvPropertyRequest{data, ..}) => {
if *data == INVERSION_AUTO {
ensure!(
self.caps.contains(fe_caps::FE_CAN_INVERSION_AUTO),
@ -238,7 +229,7 @@ impl FeDevice {
);
}
}
DTV_TRANSMISSION_MODE(DtvPropertyData{data, ..}) => {
DTV_TRANSMISSION_MODE(DtvPropertyRequest{data, ..}) => {
if *data == TRANSMISSION_MODE_AUTO {
ensure!(
self.caps.contains(fe_caps::FE_CAN_TRANSMISSION_MODE_AUTO),
@ -246,7 +237,7 @@ impl FeDevice {
);
}
}
DTV_GUARD_INTERVAL(DtvPropertyData{data, ..}) => {
DTV_GUARD_INTERVAL(DtvPropertyRequest{data, ..}) => {
if *data == GUARD_INTERVAL_AUTO {
ensure!(
self.caps.contains(fe_caps::FE_CAN_GUARD_INTERVAL_AUTO),
@ -254,7 +245,7 @@ impl FeDevice {
);
}
}
DTV_HIERARCHY(DtvPropertyData{data, ..}) => {
DTV_HIERARCHY(DtvPropertyRequest{data, ..}) => {
if *data == HIERARCHY_AUTO {
ensure!(
self.caps.contains(fe_caps::FE_CAN_HIERARCHY_AUTO),

View File

@ -243,21 +243,17 @@ impl FeStatus {
DTV_STAT_CNR,
DTV_STAT_PRE_ERROR_BIT_COUNT,
DTV_STAT_ERROR_BLOCK_COUNT
);
self.delivery_system = delivery_system;
self.modulation = modulation;
if let Some(v) = snr {
self.normalize_snr(v);
}
if let Some(v) = signal_strength {
self.normalize_signal_strength(v);
}
self.ber = match ber.and_then(|v| v.get_counter()) {
)?;
self.delivery_system = Some(delivery_system);
self.modulation = Some(modulation);
self.normalize_signal_strength(signal_strength);
self.normalize_snr(snr);
self.ber = match ber.get_counter() {
Some(v) => Some(v),
None if self.status.contains(fe_status::FE_HAS_LOCK) => Some(fe.read_ber()?),
None => None,
};
self.unc = match unc.and_then(|v| v.get_counter()) {
self.unc = match unc.get_counter() {
Some(v) => Some(v),
None if self.status.contains(fe_status::FE_HAS_LOCK) => Some(fe.read_unc()?),
None => None,

View File

@ -1,4 +1,5 @@
use std::{fmt, mem};
use anyhow::{Context};
use std::{fmt, mem, iter::{FromIterator}};
pub use {
fe_code_rate::*, fe_delivery_system::*, fe_guard_interval::*, fe_hierarchy::*,
@ -193,7 +194,7 @@ pub enum fe_sec_voltage {
#[repr(u32)]
#[allow(non_camel_case_types)]
#[derive(Debug,Copy, Clone, PartialEq, Eq, FromRepr)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, FromRepr)]
pub enum fe_sec_tone_mode {
/// Sends a 22kHz tone burst to the antenna
SEC_TONE_ON = 0,
@ -412,12 +413,6 @@ pub enum fe_delivery_system {
SYS_DVBC2 = 19,
}
impl Default for fe_delivery_system {
fn default() -> fe_delivery_system {
SYS_UNDEFINED
}
}
#[repr(u32)]
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, FromRepr, Copy, Clone)]
@ -432,6 +427,10 @@ pub trait WrappedSlice<T> {
fn slice(&self) -> &[T];
}
pub trait WrappedResult<T> {
fn get(&self) -> anyhow::Result<T>;
}
pub trait DtvStatType {
fn get_decibel(&self) -> Option<i64>;
fn get_relative(&self) -> Option<u16>;
@ -518,21 +517,6 @@ pub struct DtvFrontendStats {
stat: [DtvStat; MAX_DTV_STATS],
}
impl Default for DtvFrontendStats {
fn default() -> Self {
unsafe { mem::zeroed::<Self>() }
}
}
impl DtvFrontendStats {
pub fn new(stat: DtvStat) -> Self {
let mut result = Self::default();
result.len = 1;
result.stat[0] = stat;
result
}
}
impl WrappedSlice<DtvStat> for DtvFrontendStats {
fn slice(&self) -> &[DtvStat] {
let len = ::std::cmp::min(self.len as usize, self.stat.len());
@ -540,9 +524,15 @@ impl WrappedSlice<DtvStat> for DtvFrontendStats {
}
}
impl fmt::Debug for DtvFrontendStats {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entries(self.slice().into_iter()).finish()
}
}
impl DtvStatType for DtvFrontendStats {
fn get_decibel(&self) -> Option<i64> {
for stat in self.into_iter() {
for stat in self.slice() {
if let Some(v) = stat.get_decibel() {
return Some(v);
}
@ -550,7 +540,7 @@ impl DtvStatType for DtvFrontendStats {
None
}
fn get_relative(&self) -> Option<u16> {
for stat in self.into_iter() {
for stat in self.slice() {
if let Some(v) = stat.get_relative() {
return Some(v);
}
@ -558,7 +548,7 @@ impl DtvStatType for DtvFrontendStats {
None
}
fn get_counter(&self) -> Option<u64> {
for stat in self.into_iter() {
for stat in self.slice() {
if let Some(v) = stat.get_counter() {
return Some(v);
}
@ -567,22 +557,7 @@ impl DtvStatType for DtvFrontendStats {
}
}
impl<'a> IntoIterator for &'a DtvFrontendStats {
type Item = &'a DtvStat;
type IntoIter = core::slice::Iter<'a, DtvStat>;
fn into_iter(self) -> Self::IntoIter {
self.slice().iter()
}
}
impl fmt::Debug for DtvFrontendStats {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entries(self.into_iter()).finish()
}
}
#[repr(C)]
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct DtvPropertyBuffer {
data: [u8; 32],
@ -591,13 +566,6 @@ pub struct DtvPropertyBuffer {
__reserved_2: *mut std::ffi::c_void,
}
impl Default for DtvPropertyBuffer {
#[inline]
fn default() -> Self {
unsafe { mem::zeroed::<Self>() }
}
}
impl WrappedSlice<u8> for DtvPropertyBuffer {
fn slice(&self) -> &[u8] {
let len = ::std::cmp::min(self.len as usize, self.data.len());
@ -605,30 +573,21 @@ impl WrappedSlice<u8> for DtvPropertyBuffer {
}
}
impl<'a> IntoIterator for &'a DtvPropertyBuffer {
type Item = &'a u8;
type IntoIter = core::slice::Iter<'a, u8>;
fn into_iter(self) -> Self::IntoIter {
self.slice().iter()
}
}
impl fmt::Debug for DtvPropertyBuffer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entries(self.into_iter()).finish()
f.debug_list().entries(self.slice().into_iter()).finish()
}
}
#[repr(C, packed)]
#[derive(Debug)]
pub struct DtvPropertyData<T> {
pub struct DtvPropertyRequest<T> {
__reserved: [u32; 3],
pub data: T,
pub result: i32,
data: T,
result: i32, // Unused
}
impl<T> DtvPropertyData<T> {
impl<T> DtvPropertyRequest<T> {
#[inline]
pub fn new(data: T) -> Self {
Self {
@ -639,16 +598,34 @@ impl<T> DtvPropertyData<T> {
}
}
impl<T> Default for DtvPropertyData<T> {
impl<T> Default for DtvPropertyRequest<T> {
#[inline]
fn default() -> Self {
unsafe { mem::zeroed::<Self>() }
}
}
pub type DtvPropertyRequestStats = DtvPropertyData<DtvFrontendStats>;
pub type DtvPropertyRequestData = DtvPropertyData<DtvPropertyBuffer>;
pub type DtvPropertyRequest = DtvPropertyData<u32>;
impl<T: Copy> WrappedResult<T> for DtvPropertyRequest<T> {
#[inline]
fn get(&self) -> anyhow::Result<T> {
Ok(self.data)
}
}
pub type DtvPropertyRequestVoid = DtvPropertyRequest<u32>;
pub type DtvPropertyRequestDeliverySystems = DtvPropertyRequest<DtvPropertyBuffer>;
impl<T: FromIterator<fe_delivery_system>> WrappedResult<T> for DtvPropertyRequestDeliverySystems {
#[inline]
fn get(&self) -> Result<T, anyhow::Error> {
self.data
.slice()
.into_iter()
.map(|&x| fe_delivery_system::from_repr(x as u32).context("Invalid delivery system"))
.try_collect()
}
}
#[repr(C, packed)]
#[derive(Debug)]
@ -670,74 +647,74 @@ type DtvPropertyDeprecated = DtvPropertyNotImplementedLinux;
#[allow(deprecated)]
pub enum DtvProperty {
DTV_UNDEFINED(DtvPropertyNotImplementedLinux),
DTV_TUNE(DtvPropertyRequest),
DTV_CLEAR(DtvPropertyRequest),
DTV_FREQUENCY(DtvPropertyData<u32>),
DTV_MODULATION(DtvPropertyData<fe_modulation>),
DTV_BANDWIDTH_HZ(DtvPropertyData<u32>),
DTV_INVERSION(DtvPropertyData<fe_spectral_inversion>),
DTV_TUNE(DtvPropertyRequestVoid),
DTV_CLEAR(DtvPropertyRequestVoid),
DTV_FREQUENCY(DtvPropertyRequest<u32>),
DTV_MODULATION(DtvPropertyRequest<fe_modulation>),
DTV_BANDWIDTH_HZ(DtvPropertyRequest<u32>),
DTV_INVERSION(DtvPropertyRequest<fe_spectral_inversion>),
DTV_DISEQC_MASTER(DtvPropertyNotImplementedLinux),
DTV_SYMBOL_RATE(DtvPropertyData<u32>),
DTV_INNER_FEC(DtvPropertyData<fe_code_rate>),
DTV_VOLTAGE(DtvPropertyData<fe_sec_voltage>),
DTV_TONE(DtvPropertyData<fe_sec_tone_mode>),
DTV_PILOT(DtvPropertyData<fe_pilot>),
DTV_ROLLOFF(DtvPropertyData<fe_rolloff>),
DTV_SYMBOL_RATE(DtvPropertyRequest<u32>),
DTV_INNER_FEC(DtvPropertyRequest<fe_code_rate>),
DTV_VOLTAGE(DtvPropertyRequest<fe_sec_voltage>),
DTV_TONE(DtvPropertyRequest<fe_sec_tone_mode>),
DTV_PILOT(DtvPropertyRequest<fe_pilot>),
DTV_ROLLOFF(DtvPropertyRequest<fe_rolloff>),
DTV_DISEQC_SLAVE_REPLY(DtvPropertyNotImplementedLinux),
/* Basic enumeration set for querying unlimited capabilities */
DTV_FE_CAPABILITY_COUNT(DtvPropertyNotImplementedLinux),
DTV_FE_CAPABILITY(DtvPropertyNotImplementedLinux),
DTV_DELIVERY_SYSTEM(DtvPropertyData<fe_delivery_system>),
DTV_DELIVERY_SYSTEM(DtvPropertyRequest<fe_delivery_system>),
/* ISDB-T and ISDB-Tsb */
// Please fork
DTV_ISDBT_PARTIAL_RECEPTION(DtvPropertyData<i32>),
DTV_ISDBT_SOUND_BROADCASTING(DtvPropertyData<i32>),
DTV_ISDBT_PARTIAL_RECEPTION(DtvPropertyRequest<i32>),
DTV_ISDBT_SOUND_BROADCASTING(DtvPropertyRequest<i32>),
DTV_ISDBT_SB_SUBCHANNEL_ID(DtvPropertyData<i32>),
DTV_ISDBT_SB_SEGMENT_IDX(DtvPropertyData<i32>),
DTV_ISDBT_SB_SEGMENT_COUNT(DtvPropertyData<u32>),
DTV_ISDBT_SB_SUBCHANNEL_ID(DtvPropertyRequest<i32>),
DTV_ISDBT_SB_SEGMENT_IDX(DtvPropertyRequest<i32>),
DTV_ISDBT_SB_SEGMENT_COUNT(DtvPropertyRequest<u32>),
DTV_ISDBT_LAYERA_FEC(DtvPropertyData<fe_code_rate>),
DTV_ISDBT_LAYERA_MODULATION(DtvPropertyData<fe_modulation>),
DTV_ISDBT_LAYERA_SEGMENT_COUNT(DtvPropertyData<i32>),
DTV_ISDBT_LAYERA_TIME_INTERLEAVING(DtvPropertyData<i32>),
DTV_ISDBT_LAYERA_FEC(DtvPropertyRequest<fe_code_rate>),
DTV_ISDBT_LAYERA_MODULATION(DtvPropertyRequest<fe_modulation>),
DTV_ISDBT_LAYERA_SEGMENT_COUNT(DtvPropertyRequest<i32>),
DTV_ISDBT_LAYERA_TIME_INTERLEAVING(DtvPropertyRequest<i32>),
DTV_ISDBT_LAYERB_FEC(DtvPropertyData<fe_code_rate>),
DTV_ISDBT_LAYERB_MODULATION(DtvPropertyData<fe_modulation>),
DTV_ISDBT_LAYERB_SEGMENT_COUNT(DtvPropertyData<i32>),
DTV_ISDBT_LAYERB_TIME_INTERLEAVING(DtvPropertyData<i32>),
DTV_ISDBT_LAYERB_FEC(DtvPropertyRequest<fe_code_rate>),
DTV_ISDBT_LAYERB_MODULATION(DtvPropertyRequest<fe_modulation>),
DTV_ISDBT_LAYERB_SEGMENT_COUNT(DtvPropertyRequest<i32>),
DTV_ISDBT_LAYERB_TIME_INTERLEAVING(DtvPropertyRequest<i32>),
DTV_ISDBT_LAYERC_FEC(DtvPropertyData<fe_code_rate>),
DTV_ISDBT_LAYERC_MODULATION(DtvPropertyData<fe_modulation>),
DTV_ISDBT_LAYERC_SEGMENT_COUNT(DtvPropertyData<i32>),
DTV_ISDBT_LAYERC_TIME_INTERLEAVING(DtvPropertyData<i32>),
DTV_ISDBT_LAYERC_FEC(DtvPropertyRequest<fe_code_rate>),
DTV_ISDBT_LAYERC_MODULATION(DtvPropertyRequest<fe_modulation>),
DTV_ISDBT_LAYERC_SEGMENT_COUNT(DtvPropertyRequest<i32>),
DTV_ISDBT_LAYERC_TIME_INTERLEAVING(DtvPropertyRequest<i32>),
DTV_API_VERSION(DtvPropertyRequest),
DTV_API_VERSION(DtvPropertyRequest<u32>),
/* DVB-T/T2 */
DTV_CODE_RATE_HP(DtvPropertyData<fe_transmit_mode>),
DTV_CODE_RATE_LP(DtvPropertyData<fe_transmit_mode>),
DTV_GUARD_INTERVAL(DtvPropertyData<fe_guard_interval>),
DTV_TRANSMISSION_MODE(DtvPropertyData<fe_transmit_mode>),
DTV_HIERARCHY(DtvPropertyData<fe_hierarchy>),
DTV_CODE_RATE_HP(DtvPropertyRequest<fe_transmit_mode>),
DTV_CODE_RATE_LP(DtvPropertyRequest<fe_transmit_mode>),
DTV_GUARD_INTERVAL(DtvPropertyRequest<fe_guard_interval>),
DTV_TRANSMISSION_MODE(DtvPropertyRequest<fe_transmit_mode>),
DTV_HIERARCHY(DtvPropertyRequest<fe_hierarchy>),
DTV_ISDBT_LAYER_ENABLED(DtvPropertyData<u32>),
DTV_ISDBT_LAYER_ENABLED(DtvPropertyRequest<u32>),
DTV_STREAM_ID(DtvPropertyData<u32>),
DTV_STREAM_ID(DtvPropertyRequest<u32>),
#[deprecated(note = "Obsolete, replaced with DTV_STREAM_ID.")]
DTV_DVBT2_PLP_ID_LEGACY(DtvPropertyDeprecated),
DTV_ENUM_DELSYS(DtvPropertyRequestData),
DTV_ENUM_DELSYS(DtvPropertyRequestDeliverySystems),
/* ATSC-MH */
DTV_ATSCMH_FIC_VER(DtvPropertyData<u32>),
DTV_ATSCMH_PARADE_ID(DtvPropertyData<u32>),
DTV_ATSCMH_NOG(DtvPropertyData<u32>),
DTV_ATSCMH_TNOG(DtvPropertyData<u32>),
DTV_ATSCMH_SGN(DtvPropertyData<u32>),
DTV_ATSCMH_PRC(DtvPropertyData<u32>),
DTV_ATSCMH_FIC_VER(DtvPropertyRequest<u32>),
DTV_ATSCMH_PARADE_ID(DtvPropertyRequest<u32>),
DTV_ATSCMH_NOG(DtvPropertyRequest<u32>),
DTV_ATSCMH_TNOG(DtvPropertyRequest<u32>),
DTV_ATSCMH_SGN(DtvPropertyRequest<u32>),
DTV_ATSCMH_PRC(DtvPropertyRequest<u32>),
DTV_ATSCMH_RS_FRAME_MODE(DtvPropertyNotImplemented),
DTV_ATSCMH_RS_FRAME_ENSEMBLE(DtvPropertyNotImplemented),
DTV_ATSCMH_RS_CODE_MODE_PRI(DtvPropertyNotImplemented),
@ -748,61 +725,51 @@ pub enum DtvProperty {
DTV_ATSCMH_SCCC_CODE_MODE_C(DtvPropertyNotImplemented),
DTV_ATSCMH_SCCC_CODE_MODE_D(DtvPropertyNotImplemented),
DTV_INTERLEAVING(DtvPropertyData<fe_interleaving>),
DTV_LNA(DtvPropertyData<fe_lna>),
DTV_INTERLEAVING(DtvPropertyRequest<fe_interleaving>),
DTV_LNA(DtvPropertyRequest<fe_lna>),
/* Quality parameters */
DTV_STAT_SIGNAL_STRENGTH(DtvPropertyRequestStats),
DTV_STAT_CNR(DtvPropertyRequestStats),
DTV_STAT_PRE_ERROR_BIT_COUNT(DtvPropertyRequestStats),
DTV_STAT_PRE_TOTAL_BIT_COUNT(DtvPropertyRequestStats),
DTV_STAT_POST_ERROR_BIT_COUNT(DtvPropertyRequestStats),
DTV_STAT_POST_TOTAL_BIT_COUNT(DtvPropertyRequestStats),
DTV_STAT_ERROR_BLOCK_COUNT(DtvPropertyRequestStats),
DTV_STAT_TOTAL_BLOCK_COUNT(DtvPropertyRequestStats),
DTV_STAT_SIGNAL_STRENGTH(DtvPropertyRequest<DtvFrontendStats>),
DTV_STAT_CNR(DtvPropertyRequest<DtvFrontendStats>),
DTV_STAT_PRE_ERROR_BIT_COUNT(DtvPropertyRequest<DtvFrontendStats>),
DTV_STAT_PRE_TOTAL_BIT_COUNT(DtvPropertyRequest<DtvFrontendStats>),
DTV_STAT_POST_ERROR_BIT_COUNT(DtvPropertyRequest<DtvFrontendStats>),
DTV_STAT_POST_TOTAL_BIT_COUNT(DtvPropertyRequest<DtvFrontendStats>),
DTV_STAT_ERROR_BLOCK_COUNT(DtvPropertyRequest<DtvFrontendStats>),
DTV_STAT_TOTAL_BLOCK_COUNT(DtvPropertyRequest<DtvFrontendStats>),
/* Physical layer scrambling */
DTV_SCRAMBLING_SEQUENCE_INDEX(DtvPropertyRequest),
DTV_SCRAMBLING_SEQUENCE_INDEX(DtvPropertyRequest<u32>),
}
#[macro_export]
macro_rules! dtv_property {
( $property:ident, $data:expr ) => {
$property(DtvPropertyData::new($data))
$property(DtvPropertyRequest::new($data))
};
( $property:ident($data:expr) ) => {
$property(DtvPropertyData::new($data))
$property(DtvPropertyRequest::new($data))
};
( $property:expr ) => {
$property
};
}
#[macro_export]
macro_rules! get_dtv_property {
( $expression:expr, $property:ident ) => {{
match $expression {
$property(d) => ::std::option::Option::Some(d.data),
_ => ::std::option::Option::None,
}
}};
}
#[macro_export]
macro_rules! req_dtv_properties {
( $device:expr, $( $property:ident ),+ ) => { {
let mut input = [ $( $property(DtvPropertyData::default()), )* ];
( $device:expr, $( $property:ident ),+ ) => { (|| -> anyhow::Result<_> {
let mut input = [ $( $property(DtvPropertyRequest::default()), )* ];
$device.get_properties(&mut input)?;
let mut iterator = input.iter();
(
Ok((
$(
(match iterator.next() {
Some($property(d)) => ::std::option::Option::Some(d.data),
_ => ::std::option::Option::None,
}),
match iterator.next() {
Some($property(d)) => d.get(),
_ => ::anyhow::Result::Err(anyhow!("Error unpacking")),
}?,
)*
)
}}
))
})()}
}
/// num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl

View File

@ -1,3 +1,4 @@
#![feature(iterator_try_collect)]
#[macro_use]
extern crate anyhow;