1
0
mirror of https://github.com/danog/libdvb.git synced 2024-11-30 04:19:00 +01:00

verbosity for FeStatus::display(); FeDevice::new() rename to FeDevice::open(); AsRef for FeDevice::open()

This commit is contained in:
Andrey Dyldin 2020-10-26 14:14:35 +02:00
parent dfe7be0616
commit 68e4f734bb
4 changed files with 145 additions and 9 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "libdvb"
version = "0.2.0"
version = "0.2.1"
authors = ["Cesbo Developers Team"]
edition = "2018"

48
README.md Normal file
View File

@ -0,0 +1,48 @@
# libdvb
libdvb is an interface library to DVB devices.
Supports three types of delivery systems:
- Satellite: DVB-S, DVB-S2
- Terretrial: DVB-T, DVB-T2, ATSC, ISDB-T
- Cable: DVB-C
Implements next standards:
- Linux DVB API version 5
TODO:
- Cenelec EN 50221 - Common Interface Specification for Conditional Access and
other Digital Video BroadcastingDecoder Applications
- DiSEqC 1.0
- DiSEqC 1.1
- EN 50494 - Unicable I
- EN 50607 - Unicable II
- ISO/IEC 13818-1 - MPEG-TS
- ETSI TS 101 211 - Service Information implementation
- ETSI TR 101 290 - Measurements for DVB systems
## FeDevice
Example DVB-S2 tune:
```
let cmdseq = vec![
DtvProperty::new(DTV_DELIVERY_SYSTEM, SYS_DVBS2),
DtvProperty::new(DTV_FREQUENCY, (11044 - 9750) * 1000),
DtvProperty::new(DTV_MODULATION, PSK_8),
DtvProperty::new(DTV_VOLTAGE, SEC_VOLTAGE_13),
DtvProperty::new(DTV_TONE, SEC_TONE_OFF),
DtvProperty::new(DTV_INVERSION, INVERSION_AUTO),
DtvProperty::new(DTV_SYMBOL_RATE, 27500 * 1000),
DtvProperty::new(DTV_INNER_FEC, FEC_AUTO),
DtvProperty::new(DTV_PILOT, PILOT_AUTO),
DtvProperty::new(DTV_ROLLOFF, ROLLOFF_35),
DtvProperty::new(DTV_TUNE, 0),
];
let fe = FeDevice::open("/dev/dvb/adapter0/frontend0", true)?;
fe.ioctl_set_property(&mut cmdseq)?;
```

View File

@ -50,6 +50,7 @@ pub use {
};
/// The error type for frontend operations
#[derive(Debug, Error)]
pub enum FeError {
#[error("frontend is not char device")]
@ -73,6 +74,7 @@ pub enum FeError {
}
/// A reference to the frontend device and device information
#[derive(Debug)]
pub struct FeDevice {
file: File,
@ -125,12 +127,14 @@ impl AsRawFd for FeDevice {
impl FeDevice {
/// System call for frontend device
#[inline]
pub fn ioctl<T>(&self, request: IoctlInt, argp: T) -> Result<()> {
ioctl(self.as_raw_fd(), request, argp).context("fe ioctl")?;
Ok(())
}
/// Clears frontend settings and event queue
pub fn clear(&self) -> Result<()> {
let mut cmdseq = [
DtvProperty::new(DTV_VOLTAGE, SEC_VOLTAGE_OFF),
@ -261,12 +265,14 @@ impl FeDevice {
Ok(())
}
pub fn new(path: &Path, write: bool) -> Result<FeDevice> {
/// Attempts to open frontend device and get frontend information
/// If `write` is true opens frontend in Read-Write mode
pub fn open<P: AsRef<Path>>(path: P, write: bool) -> Result<FeDevice> {
let file = OpenOptions::new()
.read(true)
.write(write)
.custom_flags(::libc::O_NONBLOCK)
.open(path)
.open(path.as_ref())
.context("fe open")?;
let mut fe = FeDevice {
@ -344,6 +350,7 @@ impl FeDevice {
Ok(())
}
/// Sets properties on frontend device
pub fn ioctl_set_property(&self, cmdseq: &mut [DtvProperty]) -> Result<()> {
self.check_cmdseq(cmdseq).context("fe property check")?;
@ -351,11 +358,15 @@ impl FeDevice {
self.ioctl(FE_SET_PROPERTY, cmd.as_ptr())
}
/// Gets properties from frontend device
pub fn ioctl_get_property(&self, cmdseq: &mut [DtvProperty]) -> Result<()> {
let mut cmd = DtvProperties::new(cmdseq);
self.ioctl(FE_GET_PROPERTY, cmd.as_mut_ptr())
}
/// Returns the current API version
/// major - first byte
/// minor - second byte
#[inline]
pub fn get_api_version(&self) -> u16 {
self.api_version

View File

@ -10,9 +10,10 @@ use {
};
/// Frontend status
#[derive(Default, Debug, Copy, Clone)]
pub struct FeStatus {
/// sys::frontend::fe_status
/// `sys::frontend::fe_status`
status: u32,
/// signal level in dBm
@ -29,13 +30,75 @@ pub struct FeStatus {
}
/// Helper struct for displaying frontend status
pub struct FeStatusDisplay<'a> {
inner: &'a FeStatus,
verbose: u32,
}
impl<'a> fmt::Display for FeStatusDisplay<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl<'a> FeStatusDisplay<'a> {
fn display_0(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Status:")?;
if self.inner.status == FE_NONE {
write!(f, "OFF")?;
return Ok(());
}
const STATUS_MAP: &[char] = &['S', 'C', 'V', 'Y', 'L'];
for (i, s) in STATUS_MAP.iter().enumerate() {
let c = if self.inner.status & (1 << i) != 0 { *s } else { '_' };
write!(f, "{}", c)?;
}
if self.inner.status & FE_HAS_SIGNAL == 0 {
return Ok(());
}
write!(f, " S:")?;
if let Some(signal) = self.inner.signal {
// TODO: config for lo/hi
let lo: f64 = -85.0;
let hi: f64 = -6.0;
let relative = 100.0 - (signal - hi) * 100.0 / (lo - hi);
write!(f, "{:.0}% ({:.02}dBm)", relative, signal)?;
} else {
write!(f, "-")?;
}
if self.inner.status & FE_HAS_CARRIER == 0 {
return Ok(());
}
write!(f, " Q:")?;
if let Some(snr) = self.inner.snr {
let relative = 5 * snr as u32;
write!(f, "{}% ({:.02}dB)", relative, snr)?;
} else {
write!(f, "-")?;
}
if self.inner.status & FE_HAS_LOCK == 0 {
return Ok(());
}
write!(f, " BER: ")?;
if let Some(ber) = self.inner.ber {
write!(f, "{}", ber & 0xFFFF)?;
} else {
write!(f, "-")?;
}
write!(f, " UNC: ")?;
if let Some(unc) = self.inner.unc {
write!(f, "{}", unc & 0xFFFF)
} else {
write!(f, "-")
}
}
fn display_1(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Status:")?;
if self.inner.status == FE_NONE {
@ -90,8 +153,6 @@ impl<'a> fmt::Display for FeStatusDisplay<'a> {
write!(f, "-")?;
}
// Last line without new line
write!(f, "\nUNC: ")?;
if let Some(unc) = self.inner.unc {
write!(f, "{}", unc & 0xFFFF)
@ -102,13 +163,29 @@ impl<'a> fmt::Display for FeStatusDisplay<'a> {
}
impl<'a> fmt::Display for FeStatusDisplay<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.verbose {
1 => self.display_1(f),
_ => self.display_0(f),
}
}
}
impl FeStatus {
pub fn display(&self) -> FeStatusDisplay {
/// Returns an object that implements `Display` for different verbosity levels
/// Verbosity levels:
/// 0 - single line status
/// 1 - full report
pub fn display(&self, verbose: u32) -> FeStatusDisplay {
FeStatusDisplay {
inner: self,
verbose,
}
}
/// Reads frontend status
pub fn read(&mut self, fe: &FeDevice) -> Result<()> {
self.status = FE_NONE;
fe.ioctl(FE_READ_STATUS, &mut self.status as *mut _)?;