From d7cfa1618b5537ffc19af8220c1ff358dc18f3c9 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 19 Mar 2022 22:07:29 +0100 Subject: [PATCH] Finally compiling --- README.md | 29 ++++---- src/fe/mod.rs | 154 +++++++++++++++++++++------------------ src/fe/status.rs | 4 +- src/fe/sys.rs | 184 ++++++++++++++++++++++------------------------- 4 files changed, 185 insertions(+), 186 deletions(-) diff --git a/README.md b/README.md index 8732956..61a7bfd 100644 --- a/README.md +++ b/README.md @@ -22,22 +22,21 @@ TODO: Example DVB-S2 tune: ```rust -let cmdseq = vec![ - dtv_property!(DTV_DELIVERY_SYSTEM, SYS_DVBS2), - dtv_property!(DTV_FREQUENCY, (11044 - 9750) * 1000), - dtv_property!(DTV_MODULATION, PSK_8), - dtv_property!(DTV_VOLTAGE, SEC_VOLTAGE_13), - dtv_property!(DTV_TONE, SEC_TONE_OFF), - dtv_property!(DTV_INVERSION, INVERSION_AUTO), - dtv_property!(DTV_SYMBOL_RATE, 27500 * 1000), - dtv_property!(DTV_INNER_FEC, FEC_AUTO), - dtv_property!(DTV_PILOT, PILOT_AUTO), - dtv_property!(DTV_ROLLOFF, ROLLOFF_35), - dtv_property!(DTV_TUNE, 0), -]; - let fe = FeDevice::open_rw(0, 0)?; -fe.set_properties(&cmdseq)?; +set_dtv_properties!( + fe, + DTV_DELIVERY_SYSTEM(SYS_DVBS2), + DTV_FREQUENCY((11044 - 9750) * 1000), + DTV_MODULATION(PSK_8), + DTV_VOLTAGE(SEC_VOLTAGE_13), + DTV_TONE(SEC_TONE_OFF), + DTV_INVERSION(INVERSION_AUTO), + DTV_SYMBOL_RATE(27500 * 1000), + DTV_INNER_FEC(FEC_AUTO), + DTV_PILOT(PILOT_AUTO), + DTV_ROLLOFF(ROLLOFF_35), + DTV_TUNE(()), +)?; ``` Frontend information: diff --git a/src/fe/mod.rs b/src/fe/mod.rs index 8590ee0..4e5fab7 100644 --- a/src/fe/mod.rs +++ b/src/fe/mod.rs @@ -1,5 +1,3 @@ -use crate::{dtv_property, req_dtv_properties}; - mod status; pub mod sys; @@ -96,15 +94,91 @@ impl AsRawFd for FeDevice { } +#[macro_export] +macro_rules! get_dtv_properties { + ( $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)) => d.get(), + _ => ::anyhow::Result::Err(anyhow!("Error unpacking")), + }?, + )* + )) + })()} +} + +#[macro_export] +macro_rules! set_dtv_properties { + ( $device:expr, $( $property:ident($data:expr) ),+ ) => { + $device.set_properties(&[ + $( set_dtv_properties!(inner $device, $property, $data), )* + ]) + }; + ( inner $device:expr, DTV_FREQUENCY, $data:expr ) => { + if !$device.frequency_range.contains($data) { + bail!("FE: frequency out of range"); + } else { + DTV_FREQUENCY(DtvPropertyRequest::new($data:expr)) + } + }; + ( inner $device:expr, DTV_SYMBOL_RATE, $data:expr ) => { + if !$device.symbolrate_range.contains($data) { + bail!("FE: symbolrate out of range"); + } else { + DTV_SYMBOL_RATE(DtvPropertyRequest::new($data:expr)) + } + }; + ( inner $device:expr, DTV_INVERSION, $data:expr ) => { + if $data == INVERSION_AUTO && !$device.caps.contains(fe_caps::FE_CAN_INVERSION_AUTO) { + bail!("FE: auto inversion is not available"); + } else { + DTV_INVERSION(DtvPropertyRequest::new($data:expr)) + } + }; + ( inner $device:expr, DTV_TRANSMISSION_MODE, $data:expr ) => { + if $data == TRANSMISSION_MODE_AUTO && !$device.caps.contains(fe_caps::FE_CAN_TRANSMISSION_MODE_AUTO) { + bail!("FE: no auto transmission mode"); + } else { + DTV_TRANSMISSION_MODE(DtvPropertyRequest::new($data:expr)) + } + }; + ( inner $device:expr, DTV_GUARD_INTERVAL, $data:expr ) => { + if $data == GUARD_INTERVAL_AUTO && !$device.caps.contains(fe_caps::FE_CAN_GUARD_INTERVAL_AUTO) { + bail!("FE: no auto guard interval"); + } + }; + ( inner $device:expr, DTV_HIERARCHY, $data:expr ) => { + if $data == HIERARCHY_AUTO && !$device.caps.contains(fe_caps::FE_CAN_HIERARCHY_AUTO) { + bail!("FE: no auto hierarchy"); + } else { + DTV_HIERARCHY(DtvPropertyRequest::new($data:expr)) + } + }; + ( inner $device:expr, DTV_STREAM_ID, $data:expr ) => { + if !$device.caps.contains(fe_caps::FE_CAN_MULTISTREAM) { + bail!("FE: no multistream"); + } else { + DTV_STREAM_ID(DtvPropertyRequest::new($data:expr)) + } + }; + ( inner $device:expr, $property:ident, $data:expr ) => { + $property(DtvPropertyRequest::new($data)) + } +} + impl FeDevice { /// Clears frontend settings and event queue pub fn clear(&self) -> Result<()> { - let cmdseq = [ - dtv_property!(DTV_VOLTAGE, SEC_VOLTAGE_OFF), - dtv_property!(DTV_TONE, SEC_TONE_OFF), - dtv_property!(DTV_CLEAR, 0), - ]; - self.set_properties(&cmdseq).context("FE: clear")?; + set_dtv_properties!( + self, + DTV_VOLTAGE(SEC_VOLTAGE_OFF), + DTV_TONE(SEC_TONE_OFF), + DTV_CLEAR(()) + ).context("FE: clear")?; let mut event = FeEvent::default(); @@ -139,7 +213,7 @@ impl FeDevice { self.caps = feinfo.caps; // DVB v5 properties - let (api_version, enum_delsys) = req_dtv_properties!( + let (api_version, enum_delsys) = get_dtv_properties!( self, DTV_API_VERSION, DTV_ENUM_DELSYS @@ -206,70 +280,8 @@ impl FeDevice { Self::open(adapter, device, true) } - fn check_properties(&self, cmdseq: &[DtvProperty]) -> Result<()> { - for p in cmdseq { - match p { - DTV_FREQUENCY(DtvPropertyRequest{data, ..}) => { - ensure!( - self.frequency_range.contains(&data), - "FE: frequency out of range" - ); - } - DTV_SYMBOL_RATE(DtvPropertyRequest{data, ..}) => { - ensure!( - self.symbolrate_range.contains(&data), - "FE: symbolrate out of range" - ); - } - DTV_INVERSION(DtvPropertyRequest{data, ..}) => { - if *data == INVERSION_AUTO { - ensure!( - self.caps.contains(fe_caps::FE_CAN_INVERSION_AUTO), - "FE: auto inversion is not available" - ); - } - } - DTV_TRANSMISSION_MODE(DtvPropertyRequest{data, ..}) => { - if *data == TRANSMISSION_MODE_AUTO { - ensure!( - self.caps.contains(fe_caps::FE_CAN_TRANSMISSION_MODE_AUTO), - "FE: no auto transmission mode" - ); - } - } - DTV_GUARD_INTERVAL(DtvPropertyRequest{data, ..}) => { - if *data == GUARD_INTERVAL_AUTO { - ensure!( - self.caps.contains(fe_caps::FE_CAN_GUARD_INTERVAL_AUTO), - "FE: no auto guard interval" - ); - } - } - DTV_HIERARCHY(DtvPropertyRequest{data, ..}) => { - if *data == HIERARCHY_AUTO { - ensure!( - self.caps.contains(fe_caps::FE_CAN_HIERARCHY_AUTO), - "FE: no auto hierarchy" - ); - } - } - DTV_STREAM_ID(..) => { - ensure!( - self.caps.contains(fe_caps::FE_CAN_MULTISTREAM), - "FE: no multistream" - ); - } - _ => {} - } - } - - Ok(()) - } - /// Sets properties on frontend device pub fn set_properties(&self, cmdseq: &[DtvProperty]) -> Result<()> { - self.check_properties(cmdseq).context("FE: property check")?; - #[repr(C)] pub struct DtvProperties { num: u32, diff --git a/src/fe/status.rs b/src/fe/status.rs index 45d1fdd..67c5c30 100644 --- a/src/fe/status.rs +++ b/src/fe/status.rs @@ -1,4 +1,4 @@ -use crate::req_dtv_properties; +use crate::get_dtv_properties; use { super::{sys::*, FeDevice}, @@ -235,7 +235,7 @@ impl FeStatus { return Ok(()); } - let (delivery_system, modulation, signal_strength, snr, ber, unc) = req_dtv_properties!( + let (delivery_system, modulation, signal_strength, snr, ber, unc) = get_dtv_properties!( fe, DTV_DELIVERY_SYSTEM, DTV_MODULATION, diff --git a/src/fe/sys.rs b/src/fe/sys.rs index be7c96a..f7a794b 100644 --- a/src/fe/sys.rs +++ b/src/fe/sys.rs @@ -240,7 +240,7 @@ bitflags! { /// Spectral band inversion #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr)] +#[derive(Debug, PartialEq, Eq, FromRepr, Clone, Copy)] pub enum fe_spectral_inversion { INVERSION_OFF = 0, INVERSION_ON = 1, @@ -249,7 +249,7 @@ pub enum fe_spectral_inversion { #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr)] +#[derive(Debug, PartialEq, Eq, FromRepr, Clone, Copy)] pub enum fe_code_rate { FEC_NONE = 0, FEC_1_2 = 1, @@ -562,8 +562,6 @@ impl DtvStatType for DtvFrontendStats { pub struct DtvPropertyBuffer { data: [u8; 32], len: u32, - __reserved_1: [u32; 3], - __reserved_2: *mut std::ffi::c_void, } impl WrappedSlice for DtvPropertyBuffer { @@ -579,42 +577,63 @@ impl fmt::Debug for DtvPropertyBuffer { } } +const DATA_SIZE: usize = 56; + #[repr(C, packed)] -#[derive(Debug)] -pub struct DtvPropertyRequest { +pub struct DtvPropertyRequest { __reserved: [u32; 3], data: T, + padding: [u8; N], result: i32, // Unused } -impl DtvPropertyRequest { +impl DtvPropertyRequest { #[inline] pub fn new(data: T) -> Self { Self { - __reserved: [0, 0, 0], + __reserved: [0; 3], data, - result: 0, + padding: [0; N], + result: 0 } } } -impl Default for DtvPropertyRequest { +impl Default for DtvPropertyRequest { #[inline] fn default() -> Self { unsafe { mem::zeroed::() } } } -impl WrappedResult for DtvPropertyRequest { +pub type DtvPropertyRequestVoid = DtvPropertyRequest<(), DATA_SIZE>; + +impl WrappedResult<()> for DtvPropertyRequestVoid { + #[inline] + fn get(&self) ->anyhow::Result<()> { + Ok(()) + } +} + +pub type DtvPropertyRequestInt = DtvPropertyRequest; + +impl WrappedResult for DtvPropertyRequestInt { #[inline] fn get(&self) -> anyhow::Result { Ok(self.data) } } -pub type DtvPropertyRequestVoid = DtvPropertyRequest; +pub type DtvPropertyRequestFrontendStats = DtvPropertyRequest; -pub type DtvPropertyRequestDeliverySystems = DtvPropertyRequest; +impl WrappedResult for DtvPropertyRequestFrontendStats { + #[inline] + fn get(&self) -> anyhow::Result { + Ok(self.data) + } +} + +pub type DtvPropertyRequestDeliverySystems = DtvPropertyRequest; impl> WrappedResult for DtvPropertyRequestDeliverySystems { #[inline] @@ -627,8 +646,8 @@ impl> WrappedResult for DtvPropertyReques } } + #[repr(C, packed)] -#[derive(Debug)] pub struct DtvPropertyNotImplementedLinux { __reserved: [u32; 6], } @@ -643,78 +662,77 @@ type DtvPropertyDeprecated = DtvPropertyNotImplementedLinux; /// DVBv5 property Commands #[repr(u32, C)] #[allow(non_camel_case_types)] -#[derive(Debug)] #[allow(deprecated)] pub enum DtvProperty { DTV_UNDEFINED(DtvPropertyNotImplementedLinux), DTV_TUNE(DtvPropertyRequestVoid), DTV_CLEAR(DtvPropertyRequestVoid), - DTV_FREQUENCY(DtvPropertyRequest), - DTV_MODULATION(DtvPropertyRequest), - DTV_BANDWIDTH_HZ(DtvPropertyRequest), - DTV_INVERSION(DtvPropertyRequest), + DTV_FREQUENCY(DtvPropertyRequestInt), + DTV_MODULATION(DtvPropertyRequestInt), + DTV_BANDWIDTH_HZ(DtvPropertyRequestInt), + DTV_INVERSION(DtvPropertyRequestInt), DTV_DISEQC_MASTER(DtvPropertyNotImplementedLinux), - DTV_SYMBOL_RATE(DtvPropertyRequest), - DTV_INNER_FEC(DtvPropertyRequest), - DTV_VOLTAGE(DtvPropertyRequest), - DTV_TONE(DtvPropertyRequest), - DTV_PILOT(DtvPropertyRequest), - DTV_ROLLOFF(DtvPropertyRequest), + DTV_SYMBOL_RATE(DtvPropertyRequestInt), + DTV_INNER_FEC(DtvPropertyRequestInt), + DTV_VOLTAGE(DtvPropertyRequestInt), + DTV_TONE(DtvPropertyRequestInt), + DTV_PILOT(DtvPropertyRequestInt), + DTV_ROLLOFF(DtvPropertyRequestInt), DTV_DISEQC_SLAVE_REPLY(DtvPropertyNotImplementedLinux), /* Basic enumeration set for querying unlimited capabilities */ DTV_FE_CAPABILITY_COUNT(DtvPropertyNotImplementedLinux), DTV_FE_CAPABILITY(DtvPropertyNotImplementedLinux), - DTV_DELIVERY_SYSTEM(DtvPropertyRequest), + DTV_DELIVERY_SYSTEM(DtvPropertyRequestInt), /* ISDB-T and ISDB-Tsb */ // Please fork - DTV_ISDBT_PARTIAL_RECEPTION(DtvPropertyRequest), - DTV_ISDBT_SOUND_BROADCASTING(DtvPropertyRequest), + DTV_ISDBT_PARTIAL_RECEPTION(DtvPropertyRequestInt), + DTV_ISDBT_SOUND_BROADCASTING(DtvPropertyRequestInt), - DTV_ISDBT_SB_SUBCHANNEL_ID(DtvPropertyRequest), - DTV_ISDBT_SB_SEGMENT_IDX(DtvPropertyRequest), - DTV_ISDBT_SB_SEGMENT_COUNT(DtvPropertyRequest), + DTV_ISDBT_SB_SUBCHANNEL_ID(DtvPropertyRequestInt), + DTV_ISDBT_SB_SEGMENT_IDX(DtvPropertyRequestInt), + DTV_ISDBT_SB_SEGMENT_COUNT(DtvPropertyRequestInt), - DTV_ISDBT_LAYERA_FEC(DtvPropertyRequest), - DTV_ISDBT_LAYERA_MODULATION(DtvPropertyRequest), - DTV_ISDBT_LAYERA_SEGMENT_COUNT(DtvPropertyRequest), - DTV_ISDBT_LAYERA_TIME_INTERLEAVING(DtvPropertyRequest), + DTV_ISDBT_LAYERA_FEC(DtvPropertyRequestInt), + DTV_ISDBT_LAYERA_MODULATION(DtvPropertyRequestInt), + DTV_ISDBT_LAYERA_SEGMENT_COUNT(DtvPropertyRequestInt), + DTV_ISDBT_LAYERA_TIME_INTERLEAVING(DtvPropertyRequestInt), - DTV_ISDBT_LAYERB_FEC(DtvPropertyRequest), - DTV_ISDBT_LAYERB_MODULATION(DtvPropertyRequest), - DTV_ISDBT_LAYERB_SEGMENT_COUNT(DtvPropertyRequest), - DTV_ISDBT_LAYERB_TIME_INTERLEAVING(DtvPropertyRequest), + DTV_ISDBT_LAYERB_FEC(DtvPropertyRequestInt), + DTV_ISDBT_LAYERB_MODULATION(DtvPropertyRequestInt), + DTV_ISDBT_LAYERB_SEGMENT_COUNT(DtvPropertyRequestInt), + DTV_ISDBT_LAYERB_TIME_INTERLEAVING(DtvPropertyRequestInt), - DTV_ISDBT_LAYERC_FEC(DtvPropertyRequest), - DTV_ISDBT_LAYERC_MODULATION(DtvPropertyRequest), - DTV_ISDBT_LAYERC_SEGMENT_COUNT(DtvPropertyRequest), - DTV_ISDBT_LAYERC_TIME_INTERLEAVING(DtvPropertyRequest), + DTV_ISDBT_LAYERC_FEC(DtvPropertyRequestInt), + DTV_ISDBT_LAYERC_MODULATION(DtvPropertyRequestInt), + DTV_ISDBT_LAYERC_SEGMENT_COUNT(DtvPropertyRequestInt), + DTV_ISDBT_LAYERC_TIME_INTERLEAVING(DtvPropertyRequestInt), - DTV_API_VERSION(DtvPropertyRequest), + DTV_API_VERSION(DtvPropertyRequestInt), /* DVB-T/T2 */ - DTV_CODE_RATE_HP(DtvPropertyRequest), - DTV_CODE_RATE_LP(DtvPropertyRequest), - DTV_GUARD_INTERVAL(DtvPropertyRequest), - DTV_TRANSMISSION_MODE(DtvPropertyRequest), - DTV_HIERARCHY(DtvPropertyRequest), + DTV_CODE_RATE_HP(DtvPropertyRequestInt), + DTV_CODE_RATE_LP(DtvPropertyRequestInt), + DTV_GUARD_INTERVAL(DtvPropertyRequestInt), + DTV_TRANSMISSION_MODE(DtvPropertyRequestInt), + DTV_HIERARCHY(DtvPropertyRequestInt), - DTV_ISDBT_LAYER_ENABLED(DtvPropertyRequest), + DTV_ISDBT_LAYER_ENABLED(DtvPropertyRequestInt), - DTV_STREAM_ID(DtvPropertyRequest), + DTV_STREAM_ID(DtvPropertyRequestInt), #[deprecated(note = "Obsolete, replaced with DTV_STREAM_ID.")] DTV_DVBT2_PLP_ID_LEGACY(DtvPropertyDeprecated), DTV_ENUM_DELSYS(DtvPropertyRequestDeliverySystems), /* ATSC-MH */ - 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_FIC_VER(DtvPropertyRequestInt), + DTV_ATSCMH_PARADE_ID(DtvPropertyRequestInt), + DTV_ATSCMH_NOG(DtvPropertyRequestInt), + DTV_ATSCMH_TNOG(DtvPropertyRequestInt), + DTV_ATSCMH_SGN(DtvPropertyRequestInt), + DTV_ATSCMH_PRC(DtvPropertyRequestInt), DTV_ATSCMH_RS_FRAME_MODE(DtvPropertyNotImplemented), DTV_ATSCMH_RS_FRAME_ENSEMBLE(DtvPropertyNotImplemented), DTV_ATSCMH_RS_CODE_MODE_PRI(DtvPropertyNotImplemented), @@ -725,51 +743,21 @@ pub enum DtvProperty { DTV_ATSCMH_SCCC_CODE_MODE_C(DtvPropertyNotImplemented), DTV_ATSCMH_SCCC_CODE_MODE_D(DtvPropertyNotImplemented), - DTV_INTERLEAVING(DtvPropertyRequest), - DTV_LNA(DtvPropertyRequest), + DTV_INTERLEAVING(DtvPropertyRequestInt), + DTV_LNA(DtvPropertyRequestInt), /* Quality parameters */ - 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), + DTV_STAT_SIGNAL_STRENGTH(DtvPropertyRequestFrontendStats), + DTV_STAT_CNR(DtvPropertyRequestFrontendStats), + DTV_STAT_PRE_ERROR_BIT_COUNT(DtvPropertyRequestFrontendStats), + DTV_STAT_PRE_TOTAL_BIT_COUNT(DtvPropertyRequestFrontendStats), + DTV_STAT_POST_ERROR_BIT_COUNT(DtvPropertyRequestFrontendStats), + DTV_STAT_POST_TOTAL_BIT_COUNT(DtvPropertyRequestFrontendStats), + DTV_STAT_ERROR_BLOCK_COUNT(DtvPropertyRequestFrontendStats), + DTV_STAT_TOTAL_BLOCK_COUNT(DtvPropertyRequestFrontendStats), /* Physical layer scrambling */ - DTV_SCRAMBLING_SEQUENCE_INDEX(DtvPropertyRequest), -} - -#[macro_export] -macro_rules! dtv_property { - ( $property:ident, $data:expr ) => { - $property(DtvPropertyRequest::new($data)) - }; - ( $property:ident($data:expr) ) => { - $property(DtvPropertyRequest::new($data)) - }; - ( $property:expr ) => { - $property - }; -} - -#[macro_export] -macro_rules! req_dtv_properties { - ( $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)) => d.get(), - _ => ::anyhow::Result::Err(anyhow!("Error unpacking")), - }?, - )* - )) - })()} + DTV_SCRAMBLING_SEQUENCE_INDEX(DtvPropertyRequestInt), } /// num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl