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

frontend: Vec for set_property(); tune: cleaning, split close() and clear()

This commit is contained in:
Andrey Dyldin 2018-10-28 13:10:34 +05:00
parent 653ace1c82
commit 3c88315090
2 changed files with 92 additions and 69 deletions

View File

@ -26,6 +26,11 @@ pub const DTV_FE_CAPABILITY_COUNT: u32 = 15;
pub const DTV_FE_CAPABILITY: u32 = 16;
pub const DTV_DELIVERY_SYSTEM: u32 = 17;
pub const DTV_API_VERSION: u32 = 35;
pub const DTV_STREAM_ID: u32 = 42;
pub const DTV_SCRAMBLING_SEQUENCE_INDEX: u32 = 70;
bitflags! {
/// Frontend capabilities
pub struct Caps: u32 {
@ -122,6 +127,7 @@ pub struct Info {
}
impl Default for Info {
#[inline]
fn default() -> Info {
unsafe { mem::zeroed::<Info>() }
}
@ -280,18 +286,19 @@ pub struct Property {
pub result: i32,
}
/// Set of command/value pairs
#[repr(C, packed)]
pub struct Properties {
/// Amount of commands stored at the struct
pub num: u32,
/// Commands
pub props: [Property; 20],
impl Default for Property {
#[inline]
fn default() -> Property {
unsafe { mem::zeroed::<Property>() }
}
}
impl Default for Properties {
fn default() -> Properties {
unsafe { mem::zeroed::<Properties>() }
impl Property {
pub fn new(cmd: u32, data: u32) -> Property {
let mut prop = Property::default();
prop.cmd = cmd;
prop.u.data = data;
prop
}
}
@ -311,6 +318,7 @@ pub struct Event {
}
impl Default for Event {
#[inline]
fn default() -> Event {
unsafe { mem::zeroed::<Event>() }
}
@ -341,10 +349,14 @@ pub fn get_info(fd: RawFd, info: &mut Info) -> io::Result<()> {
})
}
pub fn set_property(fd: RawFd, properties: &Properties) -> io::Result<()> {
pub fn set_property(fd: RawFd, props: &Vec<Property>) -> io::Result<()> {
const FE_SET_PROPERTY: libc::c_ulong = 1074818898;
#[repr(C, packed)] struct Properties(u32, *const Property);
let properties = Properties(props.len() as u32, props.as_ptr());
cvt(unsafe {
libc::ioctl(fd, FE_SET_PROPERTY, properties as *const Properties)
libc::ioctl(fd, FE_SET_PROPERTY, &properties as *const Properties)
})
}

View File

@ -6,6 +6,10 @@ use frontend;
use std::io;
use std::os::unix::io::RawFd;
pub trait Dvb {
fn open(&self) -> io::Result<RawFd>;
}
/// Adapter
pub struct Adapter {
/// Adapter number /dev/dvb/adapterX
@ -16,6 +20,44 @@ pub struct Adapter {
pub modulation: u32,
}
fn open(adapter: &Adapter) -> io::Result<RawFd> {
let path = format!("/dev/dvb/adapter{}/frontend{}", adapter.id, adapter.device);
let fd = unsafe {
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)
}
}
fn clear(fd: RawFd) -> io::Result<()> {
let cmdseq = vec![
frontend::Property::new(frontend::DTV_CLEAR, 0),
];
frontend::set_property(fd, &cmdseq)?;
let mut event = frontend::Event::default();
loop {
if let Err(e) = frontend::get_event(fd, &mut event) {
if let Some(r) = e.raw_os_error() {
if r == libc::EWOULDBLOCK {
break;
}
}
}
}
Ok(())
}
fn close(fd: RawFd) {
clear(fd).unwrap();
unsafe { libc::close(fd) };
}
/// DVB-S/S2 Unicable options
pub struct Unicable10 {
/// Slot range from 1 to 8
@ -67,14 +109,6 @@ pub struct Lnb {
pub slof: usize,
}
/// DVB-S Options
pub struct DvbS {
pub adapter: Adapter,
pub transponder: Transponder,
pub lnb: Lnb,
pub fec: u32,
}
/// DVB-S2 Options
pub struct DvbS2 {
pub adapter: Adapter,
@ -84,71 +118,48 @@ pub struct DvbS2 {
pub rof: u32,
}
/// DVB Delivery system
#[allow(non_camel_case_types)]
pub enum DvbOptions {
DVB_S2(DvbS2),
impl Dvb for DvbS2 {
fn open(&self) -> io::Result<RawFd> {
let fd = open(&self.adapter)?;
let cmdseq = vec![
frontend::Property::new(frontend::DTV_DELIVERY_SYSTEM, frontend::SYS_DVBS2),
frontend::Property::new(frontend::DTV_FREQUENCY, 0), // TODO
frontend::Property::new(frontend::DTV_MODULATION, self.adapter.modulation),
frontend::Property::new(frontend::DTV_INVERSION, frontend::INVERSION_AUTO),
frontend::Property::new(frontend::DTV_SYMBOL_RATE, 0), // TODO
frontend::Property::new(frontend::DTV_INNER_FEC, self.fec),
frontend::Property::new(frontend::DTV_PILOT, frontend::PILOT_AUTO),
frontend::Property::new(frontend::DTV_ROLLOFF, frontend::ROLLOFF_35),
frontend::Property::new(frontend::DTV_STREAM_ID, 0),
frontend::Property::new(frontend::DTV_SCRAMBLING_SEQUENCE_INDEX, 0),
frontend::Property::new(frontend::DTV_TUNE, 0),
];
frontend::set_property(fd, &cmdseq)?;
Ok(fd)
}
}
/// DVB Instance
#[derive(Default)]
pub struct DvbTune {
fd: RawFd,
info: frontend::Info,
}
impl DvbTune {
/// Clears frontend and event queue
fn clear(&self) -> io::Result<()> {
let mut cmdseq = frontend::Properties::default();
cmdseq.num = 1;
cmdseq.props[0].cmd = frontend::DTV_CLEAR;
frontend::set_property(self.fd, &mut cmdseq)?;
let mut e = frontend::Event::default();
while let Ok(_) = frontend::get_event(self.fd, &mut e) {};
Ok(())
pub fn new(dvb: &Dvb) -> io::Result<DvbTune> {
let mut x = DvbTune::default();
x.fd = dvb.open()?;
Ok(x)
}
/// Closes frontend
pub fn close(&mut self) {
if self.fd > 0 {
self.clear().unwrap();
unsafe { libc::close(self.fd) };
close(self.fd);
self.fd = 0;
}
}
/// Opens fronted
fn open(&mut self, adapter: &Adapter) -> io::Result<()> {
let path = format!("/dev/dvb/adapter{}/frontend{}", adapter.id, adapter.device);
self.fd = unsafe {
libc::open(path.as_ptr() as *const i8, libc::O_NONBLOCK | libc::O_RDWR)
};
if self.fd == -1 {
self.fd = 0;
Err(io::Error::last_os_error())
} else {
frontend::get_info(self.fd, &mut self.info)
}
}
pub fn new(options: &DvbOptions) -> io::Result<DvbTune> {
let mut x = DvbTune::default();
match options {
DvbOptions::DVB_S2(v) => {
x.open(&v.adapter)?;
// TODO: continue here...
// DvbS::tune(v)?;
},
};
Ok(x)
}
}
impl Drop for DvbTune {