From a33cd90986ce0d028f70f4c9c438a5b0f9af275e Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 21 Mar 2022 19:50:58 +0100 Subject: [PATCH] Fixes --- Cargo.toml | 3 +- src/ca/apdu.rs | 2 +- src/ca/mod.rs | 1 + src/ca/spdu.rs | 1 + src/ca/tpdu.rs | 1 + src/fe/mod.rs | 115 ++++++++++++---------- src/fe/sys.rs | 251 ++++++++++++++++++++++++++++++++++++++++++------- 7 files changed, 288 insertions(+), 86 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2c9b6c7..b54f03d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libdvb-rs" -version = "0.4.0" +version = "0.4.1" description = "Safer pure-Rust interface for DVB-API v5 devices in Linux" authors = ["Cesbo Developers Team ", "Daniil Gentili "] license = "MIT" @@ -16,5 +16,4 @@ nix = "0.19" anyhow = "1.0" strum = { version = "0.23", features = ["derive"] } bitflags = "1.3.2" -derive_more = "0.99.0" itertools = "0.10.2" \ No newline at end of file diff --git a/src/ca/apdu.rs b/src/ca/apdu.rs index 18abea0..6afce5c 100644 --- a/src/ca/apdu.rs +++ b/src/ca/apdu.rs @@ -4,7 +4,7 @@ //! All protocols in the Application Layer use a common Application //! Protocol Data Unit (APDU) structure to send application data between //! module and host or between modules. - +#![allow(dead_code)] use {super::CaDevice, anyhow::Result}; pub const APDU_TAG_SIZE: usize = 3; diff --git a/src/ca/mod.rs b/src/ca/mod.rs index 302b6a9..fa59f54 100644 --- a/src/ca/mod.rs +++ b/src/ca/mod.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] mod apdu; mod asn1; mod spdu; diff --git a/src/ca/spdu.rs b/src/ca/spdu.rs index 6a78b32..d88c239 100644 --- a/src/ca/spdu.rs +++ b/src/ca/spdu.rs @@ -4,6 +4,7 @@ //! The session layer uses a Session Protocol Data Unit (SPDU) structure //! to exchange data at session level either from the host to the module //! or from the module to the host. +#![allow(dead_code)] use { super::{apdu, tpdu, CaDevice}, diff --git a/src/ca/tpdu.rs b/src/ca/tpdu.rs index 724121a..2f47472 100644 --- a/src/ca/tpdu.rs +++ b/src/ca/tpdu.rs @@ -9,6 +9,7 @@ //! Transport Protocol Data Unit (R_TPDU). //! The module cannot initiate communication: it must wait for the host to //! poll it or send it data first. +#![allow(dead_code)] use { super::{asn1, spdu, CaDevice}, diff --git a/src/fe/mod.rs b/src/fe/mod.rs index 2c12eee..a7a7958 100644 --- a/src/fe/mod.rs +++ b/src/fe/mod.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] mod status; pub mod sys; @@ -100,59 +101,9 @@ macro_rules! get_dtv_properties { macro_rules! set_dtv_properties { ( $device:expr, $( $property:ident($data:expr) ),+ ) => { $device.set_properties(&[ - $( set_dtv_properties!(inner $device, $property, $data), )* + $( $property(DtvPropertyRequest::new($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 { @@ -266,8 +217,70 @@ impl FeDevice { Self::open(adapter, device, true) } + fn check_properties(&self, cmdseq: &[DtvProperty]) -> Result<()> { + for p in cmdseq { + match p { + DTV_FREQUENCY(d) => { + ensure!( + self.frequency_range.contains(&d.get()?), + "FE: frequency out of range" + ); + } + DTV_SYMBOL_RATE(d) => { + ensure!( + self.symbolrate_range.contains(&d.get()?), + "FE: symbolrate out of range" + ); + } + DTV_INVERSION(d) => { + if d.get()? == INVERSION_AUTO { + ensure!( + self.caps.contains(fe_caps::FE_CAN_INVERSION_AUTO), + "FE: auto inversion is not available" + ); + } + } + DTV_TRANSMISSION_MODE(d) => { + if d.get()? == TRANSMISSION_MODE_AUTO { + ensure!( + self.caps.contains(fe_caps::FE_CAN_TRANSMISSION_MODE_AUTO), + "FE: no auto transmission mode" + ); + } + } + DTV_GUARD_INTERVAL(d) => { + if d.get()? == GUARD_INTERVAL_AUTO { + ensure!( + self.caps.contains(fe_caps::FE_CAN_GUARD_INTERVAL_AUTO), + "FE: no auto guard interval" + ); + } + } + DTV_HIERARCHY(d) => { + if d.get()? == 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)?; + #[repr(C)] pub struct DtvProperties { num: u32, diff --git a/src/fe/sys.rs b/src/fe/sys.rs index ca4c0b9..bf3efdf 100644 --- a/src/fe/sys.rs +++ b/src/fe/sys.rs @@ -1,5 +1,7 @@ use anyhow::Context; -use std::{fmt, iter::FromIterator, mem}; +use std::fmt::Debug; +use std::str::FromStr; +use std::{fmt, mem}; pub use { fe_code_rate::*, fe_delivery_system::*, fe_guard_interval::*, fe_hierarchy::*, @@ -182,7 +184,7 @@ impl Default for DiseqcSlaveReply { /// DC Voltage used to feed the LNBf #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, FromRepr)] +#[derive(EnumString, Debug, Copy, Clone, PartialEq, Eq, FromRepr)] pub enum fe_sec_voltage { /// Output 13V to the LNB. Vertical linear. Right circular. SEC_VOLTAGE_13 = 0, @@ -194,7 +196,7 @@ pub enum fe_sec_voltage { #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, FromRepr)] +#[derive(EnumString, Debug, Copy, Clone, PartialEq, Eq, FromRepr)] pub enum fe_sec_tone_mode { /// Sends a 22kHz tone burst to the antenna SEC_TONE_ON = 0, @@ -240,114 +242,178 @@ bitflags! { /// Spectral band inversion #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr, Clone, Copy)] +#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Clone, Copy)] pub enum fe_spectral_inversion { + #[strum(serialize = "OFF")] INVERSION_OFF = 0, + #[strum(serialize = "ON")] INVERSION_ON = 1, + #[strum(serialize = "AUTO")] INVERSION_AUTO = 2, } #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr, Clone, Copy)] +#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Clone, Copy)] +#[strum(ascii_case_insensitive)] pub enum fe_code_rate { + #[strum(serialize = "NONE")] FEC_NONE = 0, + #[strum(serialize = "1/2")] FEC_1_2 = 1, + #[strum(serialize = "2/3")] FEC_2_3 = 2, + #[strum(serialize = "3/4")] FEC_3_4 = 3, + #[strum(serialize = "4/5")] FEC_4_5 = 4, + #[strum(serialize = "5/6")] FEC_5_6 = 5, + #[strum(serialize = "6/7")] FEC_6_7 = 6, + #[strum(serialize = "7/8")] FEC_7_8 = 7, + #[strum(serialize = "8/9")] FEC_8_9 = 8, + #[strum(serialize = "AUTO")] FEC_AUTO = 9, + #[strum(serialize = "3/5")] FEC_3_5 = 10, + #[strum(serialize = "9/10")] FEC_9_10 = 11, + #[strum(serialize = "2/5")] FEC_2_5 = 12, + #[strum(serialize = "1/4")] FEC_1_4 = 13, + #[strum(serialize = "1/3")] FEC_1_3 = 14, } /// Type of modulation/constellation #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr, Copy, Clone)] +#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] pub enum fe_modulation { QPSK = 0, + #[strum(serialize = "QAM/16")] QAM_16 = 1, + #[strum(serialize = "QAM/32")] QAM_32 = 2, + #[strum(serialize = "QAM/64")] QAM_64 = 3, + #[strum(serialize = "QAM/128")] QAM_128 = 4, + #[strum(serialize = "QAM/256")] QAM_256 = 5, + #[strum(serialize = "QAM/AUTO")] QAM_AUTO = 6, + #[strum(serialize = "VSB/8")] VSB_8 = 7, + #[strum(serialize = "VSB/16")] VSB_16 = 8, + #[strum(serialize = "PSK/8")] PSK_8 = 9, + #[strum(serialize = "APSK/16")] APSK_16 = 10, + #[strum(serialize = "APSK/32")] APSK_32 = 11, + #[strum(serialize = "DQPSK")] DQPSK = 12, + #[strum(serialize = "QAM/4/NR")] QAM_4_NR = 13, + #[strum(serialize = "APSK/64")] APSK_64 = 14, + #[strum(serialize = "APSK/128")] APSK_128 = 15, + #[strum(serialize = "APSK/256")] APSK_256 = 16, } #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr, Copy, Clone)] +#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] pub enum fe_transmit_mode { + #[strum(serialize = "2K")] TRANSMISSION_MODE_2K = 0, + #[strum(serialize = "8K")] TRANSMISSION_MODE_8K = 1, + #[strum(serialize = "AUTO")] TRANSMISSION_MODE_AUTO = 2, + #[strum(serialize = "4K")] TRANSMISSION_MODE_4K = 3, + #[strum(serialize = "1K")] TRANSMISSION_MODE_1K = 4, + #[strum(serialize = "16K")] TRANSMISSION_MODE_16K = 5, + #[strum(serialize = "32K")] TRANSMISSION_MODE_32K = 6, + #[strum(serialize = "C1")] TRANSMISSION_MODE_C1 = 7, + #[strum(serialize = "C3780")] TRANSMISSION_MODE_C3780 = 8, } #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr, Copy, Clone)] +#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] pub enum fe_guard_interval { + #[strum(serialize = "1/32")] GUARD_INTERVAL_1_32 = 0, + #[strum(serialize = "1/16")] GUARD_INTERVAL_1_16 = 1, + #[strum(serialize = "1/8")] GUARD_INTERVAL_1_8 = 2, + #[strum(serialize = "1/4")] GUARD_INTERVAL_1_4 = 3, + #[strum(serialize = "AUTO")] GUARD_INTERVAL_AUTO = 4, + #[strum(serialize = "1/128")] GUARD_INTERVAL_1_128 = 5, + #[strum(serialize = "19/128")] GUARD_INTERVAL_19_128 = 6, + #[strum(serialize = "19/256")] GUARD_INTERVAL_19_256 = 7, + #[strum(serialize = "PN420")] GUARD_INTERVAL_PN420 = 8, + #[strum(serialize = "PN595")] GUARD_INTERVAL_PN595 = 9, + #[strum(serialize = "PN945")] GUARD_INTERVAL_PN945 = 10, } #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr, Copy, Clone)] +#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] pub enum fe_hierarchy { + #[strum(serialize = "NONE")] HIERARCHY_NONE = 0, + #[strum(serialize = "1")] HIERARCHY_1 = 1, + #[strum(serialize = "2")] HIERARCHY_2 = 2, + #[strum(serialize = "4")] HIERARCHY_4 = 3, + #[strum(serialize = "AUTO")] HIERARCHY_AUTO = 4, } #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr, Copy, Clone)] +#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] pub enum fe_interleaving { + #[strum(serialize = "NONE")] INTERLEAVING_NONE = 0, + #[strum(serialize = "AUTO")] INTERLEAVING_AUTO = 1, + #[strum(serialize = "240")] INTERLEAVING_240 = 2, + #[strum(serialize = "720")] INTERLEAVING_720 = 3, } #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr, Copy, Clone)] +#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] pub enum fe_pilot { PILOT_ON = 0, PILOT_OFF = 1, @@ -356,7 +422,7 @@ pub enum fe_pilot { #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr, Copy, Clone)] +#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] pub enum fe_rolloff { ROLLOFF_35 = 0, ROLLOFF_20 = 1, @@ -370,28 +436,29 @@ pub enum fe_rolloff { #[derive(EnumString, Display, FromRepr, Debug, Copy, Clone)] #[repr(u32)] #[allow(non_camel_case_types)] +#[strum(ascii_case_insensitive)] pub enum fe_delivery_system { #[strum(to_string = "none")] SYS_UNDEFINED = 0, - #[strum(to_string = "dvb-c")] + #[strum(to_string = "dbvc/annex_a")] SYS_DVBC_ANNEX_A = 1, - #[strum(to_string = "dvb-c/b")] + #[strum(to_string = "dvbc/annex_b")] SYS_DVBC_ANNEX_B = 2, - #[strum(to_string = "dvb-t")] + #[strum(to_string = "dvbt")] SYS_DVBT = 3, #[strum(to_string = "dss")] SYS_DSS = 4, - #[strum(to_string = "dvb-s")] + #[strum(to_string = "dvbs")] SYS_DVBS = 5, - #[strum(to_string = "dvb-s2")] + #[strum(to_string = "dvbs2")] SYS_DVBS2 = 6, - #[strum(to_string = "dvb-h")] + #[strum(to_string = "dvbh")] SYS_DVBH = 7, - #[strum(to_string = "isdb-t")] + #[strum(to_string = "isdbt")] SYS_ISDBT = 8, - #[strum(to_string = "isdb-s")] + #[strum(to_string = "isdbs")] SYS_ISDBS = 9, - #[strum(to_string = "isdb-c")] + #[strum(to_string = "isdbc")] SYS_ISDBC = 10, #[strum(to_string = "atsc")] SYS_ATSC = 11, @@ -403,19 +470,19 @@ pub enum fe_delivery_system { SYS_CMMB = 14, #[strum(to_string = "dab")] SYS_DAB = 15, - #[strum(to_string = "dvb-t2")] + #[strum(to_string = "dvbt2", serialize = "dvbt22")] SYS_DVBT2 = 16, - #[strum(to_string = "dvb-s/turbo")] + #[strum(to_string = "dvbs/turbo")] SYS_TURBO = 17, - #[strum(to_string = "dvb-c/c")] + #[strum(to_string = "dvbc/annex_c")] SYS_DVBC_ANNEX_C = 18, - #[strum(to_string = "dvb-c2")] + #[strum(to_string = "dvbc2")] SYS_DVBC2 = 19, } #[repr(u32)] #[allow(non_camel_case_types)] -#[derive(Debug, PartialEq, Eq, FromRepr, Copy, Clone)] +#[derive(EnumString, Debug, PartialEq, Eq, FromRepr, Copy, Clone)] pub enum fe_lna { LNA_OFF = 0, LNA_ON = 1, @@ -615,15 +682,27 @@ impl WrappedResult<()> for DtvPropertyRequestVoid { } } +impl Debug for DtvPropertyRequestVoid { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("()") + } +} + pub type DtvPropertyRequestInt = DtvPropertyRequest; -impl WrappedResult for DtvPropertyRequestInt { +impl WrappedResult for DtvPropertyRequestInt { #[inline] fn get(&self) -> anyhow::Result { Ok(self.data) } } +impl Debug for DtvPropertyRequestInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.get().fmt(f) + } +} + pub type DtvPropertyRequestFrontendStats = DtvPropertyRequest; impl WrappedResult for DtvPropertyRequestFrontendStats { @@ -633,12 +712,18 @@ impl WrappedResult for DtvPropertyRequestFrontendStats { } } +impl Debug for DtvPropertyRequestFrontendStats { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.data.fmt(f) + } +} + pub type DtvPropertyRequestDeliverySystems = DtvPropertyRequest; -impl> WrappedResult for DtvPropertyRequestDeliverySystems { +impl WrappedResult> for DtvPropertyRequestDeliverySystems { #[inline] - fn get(&self) -> Result { + fn get(&self) -> Result, anyhow::Error> { self.data .slice() .into_iter() @@ -647,9 +732,21 @@ impl> WrappedResult for DtvPropertyReques } } +impl Debug for DtvPropertyRequestDeliverySystems { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list().entries(self.get().unwrap().iter()).finish() + } +} + #[repr(C, packed)] pub struct DtvPropertyNotImplementedLinux { - __reserved: [u32; 6], + __reserved: [u8; DATA_SIZE], +} + +impl Debug for DtvPropertyNotImplementedLinux { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("Not implemented") + } } #[deprecated( @@ -663,6 +760,7 @@ type DtvPropertyDeprecated = DtvPropertyNotImplementedLinux; #[repr(u32, C)] #[allow(non_camel_case_types)] #[allow(deprecated)] +#[derive(Debug)] pub enum DtvProperty { DTV_UNDEFINED(DtvPropertyNotImplementedLinux), DTV_TUNE(DtvPropertyRequestVoid), @@ -712,8 +810,8 @@ pub enum DtvProperty { DTV_API_VERSION(DtvPropertyRequestInt), /* DVB-T/T2 */ - DTV_CODE_RATE_HP(DtvPropertyRequestInt), - DTV_CODE_RATE_LP(DtvPropertyRequestInt), + DTV_CODE_RATE_HP(DtvPropertyRequestInt), + DTV_CODE_RATE_LP(DtvPropertyRequestInt), DTV_GUARD_INTERVAL(DtvPropertyRequestInt), DTV_TRANSMISSION_MODE(DtvPropertyRequestInt), DTV_HIERARCHY(DtvPropertyRequestInt), @@ -760,6 +858,95 @@ pub enum DtvProperty { DTV_SCRAMBLING_SEQUENCE_INDEX(DtvPropertyRequestInt), } +#[macro_export] +macro_rules! dtv_property { + ( $property:ident($data:expr) ) => { + $property(DtvPropertyRequest::new($data)) + }; +} + +#[macro_export] +macro_rules! dtv_property_parse { + ( $property:ident($data:expr)) => { + $property(DtvPropertyRequest::new($data.parse().context(format!("Invalid {}: {}", stringify!($property), $data))?)) + }; +} + +impl FromStr for DtvProperty { + type Err = anyhow::Error; + fn from_str(s: &str) -> Result { + let (k, v) = s.split_once('=').context("Invalid line")?; + let v = v.trim(); + Ok(match k.trim() { + "FREQUENCY" => dtv_property_parse!(DTV_FREQUENCY(v)), + "MODULATION" => dtv_property_parse!(DTV_MODULATION(v)), + "BANDWIDTH_HZ" => dtv_property_parse!(DTV_BANDWIDTH_HZ(v)), + "INVERSION" => dtv_property_parse!(DTV_INVERSION(v)), + "SYMBOL_RATE" => dtv_property_parse!(DTV_SYMBOL_RATE(v)), + "INNER_FEC" => dtv_property_parse!(DTV_INNER_FEC(v)), + "VOLTAGE" => dtv_property_parse!(DTV_VOLTAGE(v)), + "TONE" => dtv_property_parse!(DTV_TONE(v)), + "PILOT" => dtv_property_parse!(DTV_PILOT(v)), + "ROLLOFF" => dtv_property_parse!(DTV_ROLLOFF(v)), + + /* Basic enumeration set for querying unlimited capabilities */ + "DELIVERY_SYSTEM" => dtv_property_parse!(DTV_DELIVERY_SYSTEM(v)), + + /* ISDB-T and ISDB-Tsb */ + "ISDBT_PARTIAL_RECEPTION" => dtv_property_parse!(DTV_ISDBT_PARTIAL_RECEPTION(v)), + "ISDBT_SOUND_BROADCASTING" => dtv_property_parse!(DTV_ISDBT_SOUND_BROADCASTING(v)), + + "ISDBT_SB_SUBCHANNEL_ID" => dtv_property_parse!(DTV_ISDBT_SB_SUBCHANNEL_ID(v)), + "ISDBT_SB_SEGMENT_IDX" => dtv_property_parse!(DTV_ISDBT_SB_SEGMENT_IDX(v)), + "ISDBT_SB_SEGMENT_COUNT" => dtv_property_parse!(DTV_ISDBT_SB_SEGMENT_COUNT(v)), + + "ISDBT_LAYERA_FEC" => dtv_property_parse!(DTV_ISDBT_LAYERA_FEC(v)), + "ISDBT_LAYERA_MODULATION" => dtv_property_parse!(DTV_ISDBT_LAYERA_MODULATION(v)), + "ISDBT_LAYERA_SEGMENT_COUNT" => dtv_property_parse!(DTV_ISDBT_LAYERA_SEGMENT_COUNT(v)), + "ISDBT_LAYERA_TIME_INTERLEAVING" => { + dtv_property_parse!(DTV_ISDBT_LAYERA_TIME_INTERLEAVING(v)) + } + + "ISDBT_LAYERB_FEC" => dtv_property_parse!(DTV_ISDBT_LAYERB_FEC(v)), + "ISDBT_LAYERB_MODULATION" => dtv_property_parse!(DTV_ISDBT_LAYERB_MODULATION(v)), + "ISDBT_LAYERB_SEGMENT_COUNT" => dtv_property_parse!(DTV_ISDBT_LAYERB_SEGMENT_COUNT(v)), + "ISDBT_LAYERB_TIME_INTERLEAVING" => { + dtv_property_parse!(DTV_ISDBT_LAYERB_TIME_INTERLEAVING(v)) + } + + "ISDBT_LAYERC_FEC" => dtv_property_parse!(DTV_ISDBT_LAYERC_FEC(v)), + "ISDBT_LAYERC_MODULATION" => dtv_property_parse!(DTV_ISDBT_LAYERC_MODULATION(v)), + "ISDBT_LAYERC_SEGMENT_COUNT" => dtv_property_parse!(DTV_ISDBT_LAYERC_SEGMENT_COUNT(v)), + "ISDBT_LAYERC_TIME_INTERLEAVING" => { + dtv_property_parse!(DTV_ISDBT_LAYERC_TIME_INTERLEAVING(v)) + } + + /* DVB-T/T2 */ + "CODE_RATE_HP" => dtv_property_parse!(DTV_CODE_RATE_HP(v)), + "CODE_RATE_LP" => dtv_property_parse!(DTV_CODE_RATE_LP(v)), + "GUARD_INTERVAL" => dtv_property_parse!(DTV_GUARD_INTERVAL(v)), + "TRANSMISSION_MODE" => dtv_property_parse!(DTV_TRANSMISSION_MODE(v)), + "HIERARCHY" => dtv_property_parse!(DTV_HIERARCHY(v)), + + "ISDBT_LAYER_ENABLED" => dtv_property_parse!(DTV_ISDBT_LAYER_ENABLED(v)), + + "STREAM_ID" => dtv_property_parse!(DTV_STREAM_ID(v)), + + /* ATSC-MH */ + "ATSCMH_FIC_VER" => dtv_property_parse!(DTV_ATSCMH_FIC_VER(v)), + "ATSCMH_PARADE_ID" => dtv_property_parse!(DTV_ATSCMH_PARADE_ID(v)), + "ATSCMH_NOG" => dtv_property_parse!(DTV_ATSCMH_NOG(v)), + "ATSCMH_TNOG" => dtv_property_parse!(DTV_ATSCMH_TNOG(v)), + "ATSCMH_SGN" => dtv_property_parse!(DTV_ATSCMH_SGN(v)), + "ATSCMH_PRC" => dtv_property_parse!(DTV_ATSCMH_PRC(v)), + + "INTERLEAVING" => dtv_property_parse!(DTV_INTERLEAVING(v)), + "LNA" => dtv_property_parse!(DTV_LNA(v)), + &_ => bail!("Invalid key {}", k), + }) + } +} + /// num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl pub const DTV_IOCTL_MAX_MSGS: usize = 64;