commit 5194bc7438399a668c6ad14df693b189ceafb772 Author: Andrey Dyldin Date: Wed Oct 24 02:10:08 2018 +0500 initial commit. tune: open, FE_GET_INFO diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0aa980d --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/Cargo.lock +/target +**/*.rs.bk +.vscode diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7b320db --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "dvb" +version = "0.1.0" +authors = ["Andrey Dyldin "] + +[dependencies] +libc = "0.2" +bitflags = "1.0" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..a271cc1 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,4 @@ +extern crate libc; +#[macro_use] extern crate bitflags; + +pub mod tune; diff --git a/src/tune.rs b/src/tune.rs new file mode 100644 index 0000000..fa66e10 --- /dev/null +++ b/src/tune.rs @@ -0,0 +1,122 @@ +use libc; + +use std::{io, mem, fmt, ffi}; +use std::os::unix::io::RawFd; + +pub const FE_GET_INFO: libc::c_ulong = 2158522173; /* '_IOR('o', 61, sizeof(dvb_frontend_info)) */ + +bitflags! { + pub struct fe_caps: u32 { + const FE_IS_STUPID = 0; + const FE_CAN_INVERSION_AUTO = 0x1; + const FE_CAN_FEC_1_2 = 0x2; + const FE_CAN_FEC_2_3 = 0x4; + const FE_CAN_FEC_3_4 = 0x8; + const FE_CAN_FEC_4_5 = 0x10; + const FE_CAN_FEC_5_6 = 0x20; + const FE_CAN_FEC_6_7 = 0x40; + const FE_CAN_FEC_7_8 = 0x80; + const FE_CAN_FEC_8_9 = 0x100; + const FE_CAN_FEC_AUTO = 0x200; + const FE_CAN_QPSK = 0x400; + const FE_CAN_QAM_16 = 0x800; + const FE_CAN_QAM_32 = 0x1000; + const FE_CAN_QAM_64 = 0x2000; + const FE_CAN_QAM_128 = 0x4000; + const FE_CAN_QAM_256 = 0x8000; + const FE_CAN_QAM_AUTO = 0x10000; + const FE_CAN_TRANSMISSION_MODE_AUTO = 0x20000; + const FE_CAN_BANDWIDTH_AUTO = 0x40000; + const FE_CAN_GUARD_INTERVAL_AUTO = 0x80000; + const FE_CAN_HIERARCHY_AUTO = 0x100000; + const FE_CAN_8VSB = 0x200000; + const FE_CAN_16VSB = 0x400000; + const FE_HAS_EXTENDED_CAPS = 0x800000; + const FE_CAN_MULTISTREAM = 0x4000000; + const FE_CAN_TURBO_FEC = 0x8000000; + const FE_CAN_2G_MODULATION = 0x10000000; + const FE_NEEDS_BENDING = 0x20000000; + const FE_CAN_RECOVER = 0x40000000; + const FE_CAN_MUTE_TS = 0x80000000; + } +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct dvb_frontend_info { + pub name: [libc::c_char; 128], + pub fe_type: i32, /* DEPRECATED. Use DTV_ENUM_DELSYS instead */ + pub frequency_min: u32, + pub frequency_max: u32, + pub frequency_stepsize: u32, + pub frequency_tolerance: u32, + pub symbol_rate_min: u32, + pub symbol_rate_max: u32, + pub symbol_rate_tolerance: u32, + pub notifier_delay: u32, /* DEPRECATED */ + pub caps: fe_caps, +} + +impl fmt::Debug for dvb_frontend_info { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let name = unsafe { ffi::CStr::from_ptr(self.name.as_ptr()).to_string_lossy() }; + + f.debug_struct("dvb_frontend_info") + .field("name", &name) + .field("frequency_min", &self.frequency_min) + .field("frequency_max", &self.frequency_max) + .field("frequency_stepsize", &self.frequency_stepsize) + .field("frequency_tolerance", &self.frequency_tolerance) + .field("symbol_rate_min", &self.symbol_rate_min) + .field("symbol_rate_max", &self.symbol_rate_max) + .field("symbol_rate_tolerance", &self.symbol_rate_tolerance) + .field("caps", &self.caps) + .finish() + } +} + +#[derive(Debug)] +pub struct DvbTune { + fd: RawFd, +} + +impl DvbTune { + pub fn new(adapter: usize, device: usize) -> io::Result { + let path = format!("/dev/dvb/adapter{}/frontend{}", adapter, device); + + let fd = unsafe { + let fd = libc::open(path.as_ptr() as *const i8, libc::O_NONBLOCK | libc::O_RDWR); + if fd == -1 { + Err(io::Error::last_os_error()) + } else { + Ok(fd) + } + }?; + + let feinfo = unsafe { + let mut feinfo: dvb_frontend_info = mem::zeroed(); + let x = libc::ioctl(fd, FE_GET_INFO, &mut feinfo as *mut dvb_frontend_info as *mut libc::c_void); + if x == -1 { + libc::close(fd); + Err(io::Error::last_os_error()) + } else { + Ok(feinfo) + } + }?; + + println!("{:#?}", feinfo); + + Ok(DvbTune { + fd, + }) + } +} + +impl Drop for DvbTune { + fn drop(&mut self) { + if self.fd > 0 { + unsafe { libc::close(self.fd) }; + self.fd = 0; + } + } +}