From 5b70f19bd04aa60ea1afa3925e6cea9ce1787785 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 18 Mar 2022 21:49:42 +0100 Subject: [PATCH] Refactor --- src/fe/mod.rs | 37 +++---- src/fe/status.rs | 18 ++-- src/fe/sys.rs | 255 +++++++++++++++++++++-------------------------- src/lib.rs | 1 + 4 files changed, 133 insertions(+), 178 deletions(-) diff --git a/src/fe/mod.rs b/src/fe/mod.rs index 1f0a266..8590ee0 100644 --- a/src/fe/mod.rs +++ b/src/fe/mod.rs @@ -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::() - .map(fe_delivery_system::from_repr) - .collect::>() - .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), diff --git a/src/fe/status.rs b/src/fe/status.rs index 9cb62b5..45d1fdd 100644 --- a/src/fe/status.rs +++ b/src/fe/status.rs @@ -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, diff --git a/src/fe/sys.rs b/src/fe/sys.rs index 361c954..be7c96a 100644 --- a/src/fe/sys.rs +++ b/src/fe/sys.rs @@ -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 { fn slice(&self) -> &[T]; } +pub trait WrappedResult { + fn get(&self) -> anyhow::Result; +} + pub trait DtvStatType { fn get_decibel(&self) -> Option; fn get_relative(&self) -> Option; @@ -518,21 +517,6 @@ pub struct DtvFrontendStats { stat: [DtvStat; MAX_DTV_STATS], } -impl Default for DtvFrontendStats { - fn default() -> Self { - unsafe { mem::zeroed::() } - } -} - -impl DtvFrontendStats { - pub fn new(stat: DtvStat) -> Self { - let mut result = Self::default(); - result.len = 1; - result.stat[0] = stat; - result - } -} - impl WrappedSlice for DtvFrontendStats { fn slice(&self) -> &[DtvStat] { let len = ::std::cmp::min(self.len as usize, self.stat.len()); @@ -540,9 +524,15 @@ impl WrappedSlice 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 { - 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 { - 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 { - 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::() } - } -} - impl WrappedSlice for DtvPropertyBuffer { fn slice(&self) -> &[u8] { let len = ::std::cmp::min(self.len as usize, self.data.len()); @@ -605,30 +573,21 @@ impl WrappedSlice 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 { +pub struct DtvPropertyRequest { __reserved: [u32; 3], - pub data: T, - pub result: i32, + data: T, + result: i32, // Unused } -impl DtvPropertyData { +impl DtvPropertyRequest { #[inline] pub fn new(data: T) -> Self { Self { @@ -639,16 +598,34 @@ impl DtvPropertyData { } } -impl Default for DtvPropertyData { +impl Default for DtvPropertyRequest { #[inline] fn default() -> Self { unsafe { mem::zeroed::() } } } -pub type DtvPropertyRequestStats = DtvPropertyData; -pub type DtvPropertyRequestData = DtvPropertyData; -pub type DtvPropertyRequest = DtvPropertyData; +impl WrappedResult for DtvPropertyRequest { + #[inline] + fn get(&self) -> anyhow::Result { + Ok(self.data) + } +} + +pub type DtvPropertyRequestVoid = DtvPropertyRequest; + +pub type DtvPropertyRequestDeliverySystems = DtvPropertyRequest; + +impl> WrappedResult for DtvPropertyRequestDeliverySystems { + #[inline] + fn get(&self) -> Result { + 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), - DTV_MODULATION(DtvPropertyData), - DTV_BANDWIDTH_HZ(DtvPropertyData), - DTV_INVERSION(DtvPropertyData), + DTV_TUNE(DtvPropertyRequestVoid), + DTV_CLEAR(DtvPropertyRequestVoid), + DTV_FREQUENCY(DtvPropertyRequest), + DTV_MODULATION(DtvPropertyRequest), + DTV_BANDWIDTH_HZ(DtvPropertyRequest), + DTV_INVERSION(DtvPropertyRequest), DTV_DISEQC_MASTER(DtvPropertyNotImplementedLinux), - DTV_SYMBOL_RATE(DtvPropertyData), - DTV_INNER_FEC(DtvPropertyData), - DTV_VOLTAGE(DtvPropertyData), - DTV_TONE(DtvPropertyData), - DTV_PILOT(DtvPropertyData), - DTV_ROLLOFF(DtvPropertyData), + DTV_SYMBOL_RATE(DtvPropertyRequest), + DTV_INNER_FEC(DtvPropertyRequest), + DTV_VOLTAGE(DtvPropertyRequest), + DTV_TONE(DtvPropertyRequest), + DTV_PILOT(DtvPropertyRequest), + DTV_ROLLOFF(DtvPropertyRequest), 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), + DTV_DELIVERY_SYSTEM(DtvPropertyRequest), /* ISDB-T and ISDB-Tsb */ // Please fork - DTV_ISDBT_PARTIAL_RECEPTION(DtvPropertyData), - DTV_ISDBT_SOUND_BROADCASTING(DtvPropertyData), + DTV_ISDBT_PARTIAL_RECEPTION(DtvPropertyRequest), + DTV_ISDBT_SOUND_BROADCASTING(DtvPropertyRequest), - DTV_ISDBT_SB_SUBCHANNEL_ID(DtvPropertyData), - DTV_ISDBT_SB_SEGMENT_IDX(DtvPropertyData), - DTV_ISDBT_SB_SEGMENT_COUNT(DtvPropertyData), + DTV_ISDBT_SB_SUBCHANNEL_ID(DtvPropertyRequest), + DTV_ISDBT_SB_SEGMENT_IDX(DtvPropertyRequest), + DTV_ISDBT_SB_SEGMENT_COUNT(DtvPropertyRequest), - DTV_ISDBT_LAYERA_FEC(DtvPropertyData), - DTV_ISDBT_LAYERA_MODULATION(DtvPropertyData), - DTV_ISDBT_LAYERA_SEGMENT_COUNT(DtvPropertyData), - DTV_ISDBT_LAYERA_TIME_INTERLEAVING(DtvPropertyData), + DTV_ISDBT_LAYERA_FEC(DtvPropertyRequest), + DTV_ISDBT_LAYERA_MODULATION(DtvPropertyRequest), + DTV_ISDBT_LAYERA_SEGMENT_COUNT(DtvPropertyRequest), + DTV_ISDBT_LAYERA_TIME_INTERLEAVING(DtvPropertyRequest), - DTV_ISDBT_LAYERB_FEC(DtvPropertyData), - DTV_ISDBT_LAYERB_MODULATION(DtvPropertyData), - DTV_ISDBT_LAYERB_SEGMENT_COUNT(DtvPropertyData), - DTV_ISDBT_LAYERB_TIME_INTERLEAVING(DtvPropertyData), + DTV_ISDBT_LAYERB_FEC(DtvPropertyRequest), + DTV_ISDBT_LAYERB_MODULATION(DtvPropertyRequest), + DTV_ISDBT_LAYERB_SEGMENT_COUNT(DtvPropertyRequest), + DTV_ISDBT_LAYERB_TIME_INTERLEAVING(DtvPropertyRequest), - DTV_ISDBT_LAYERC_FEC(DtvPropertyData), - DTV_ISDBT_LAYERC_MODULATION(DtvPropertyData), - DTV_ISDBT_LAYERC_SEGMENT_COUNT(DtvPropertyData), - DTV_ISDBT_LAYERC_TIME_INTERLEAVING(DtvPropertyData), + DTV_ISDBT_LAYERC_FEC(DtvPropertyRequest), + DTV_ISDBT_LAYERC_MODULATION(DtvPropertyRequest), + DTV_ISDBT_LAYERC_SEGMENT_COUNT(DtvPropertyRequest), + DTV_ISDBT_LAYERC_TIME_INTERLEAVING(DtvPropertyRequest), - DTV_API_VERSION(DtvPropertyRequest), + DTV_API_VERSION(DtvPropertyRequest), /* DVB-T/T2 */ - DTV_CODE_RATE_HP(DtvPropertyData), - DTV_CODE_RATE_LP(DtvPropertyData), - DTV_GUARD_INTERVAL(DtvPropertyData), - DTV_TRANSMISSION_MODE(DtvPropertyData), - DTV_HIERARCHY(DtvPropertyData), + DTV_CODE_RATE_HP(DtvPropertyRequest), + DTV_CODE_RATE_LP(DtvPropertyRequest), + DTV_GUARD_INTERVAL(DtvPropertyRequest), + DTV_TRANSMISSION_MODE(DtvPropertyRequest), + DTV_HIERARCHY(DtvPropertyRequest), - DTV_ISDBT_LAYER_ENABLED(DtvPropertyData), + DTV_ISDBT_LAYER_ENABLED(DtvPropertyRequest), - DTV_STREAM_ID(DtvPropertyData), + DTV_STREAM_ID(DtvPropertyRequest), #[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), - DTV_ATSCMH_PARADE_ID(DtvPropertyData), - DTV_ATSCMH_NOG(DtvPropertyData), - DTV_ATSCMH_TNOG(DtvPropertyData), - DTV_ATSCMH_SGN(DtvPropertyData), - DTV_ATSCMH_PRC(DtvPropertyData), + DTV_ATSCMH_FIC_VER(DtvPropertyRequest), + DTV_ATSCMH_PARADE_ID(DtvPropertyRequest), + DTV_ATSCMH_NOG(DtvPropertyRequest), + DTV_ATSCMH_TNOG(DtvPropertyRequest), + DTV_ATSCMH_SGN(DtvPropertyRequest), + DTV_ATSCMH_PRC(DtvPropertyRequest), 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), - DTV_LNA(DtvPropertyData), + DTV_INTERLEAVING(DtvPropertyRequest), + DTV_LNA(DtvPropertyRequest), /* 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), + DTV_STAT_CNR(DtvPropertyRequest), + DTV_STAT_PRE_ERROR_BIT_COUNT(DtvPropertyRequest), + DTV_STAT_PRE_TOTAL_BIT_COUNT(DtvPropertyRequest), + DTV_STAT_POST_ERROR_BIT_COUNT(DtvPropertyRequest), + DTV_STAT_POST_TOTAL_BIT_COUNT(DtvPropertyRequest), + DTV_STAT_ERROR_BLOCK_COUNT(DtvPropertyRequest), + DTV_STAT_TOTAL_BLOCK_COUNT(DtvPropertyRequest), /* Physical layer scrambling */ - DTV_SCRAMBLING_SEQUENCE_INDEX(DtvPropertyRequest), + DTV_SCRAMBLING_SEQUENCE_INDEX(DtvPropertyRequest), } #[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 diff --git a/src/lib.rs b/src/lib.rs index 8246a2b..716695b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(iterator_try_collect)] #[macro_use] extern crate anyhow;