mirror of
https://github.com/danog/libdvb.git
synced 2024-11-30 04:19:00 +01:00
nix crate for ioctl; FeDevice::set_properties(); FeDevice::get_properties(); FeDevice::diseqc_master_cmd(); FeDevice::get_event(); remove FeDevice::ioctl(); remove PCI/USB vendor id reading
This commit is contained in:
parent
478bcdd8dd
commit
9e949b3bbd
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "libdvb"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
description = "Interface for DVB-API v5 devices in Linux"
|
||||
authors = ["Cesbo Developers Team <info@cesbo.com>"]
|
||||
license = "MIT"
|
||||
@ -13,5 +13,6 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
nix = "0.19"
|
||||
anyhow = "1.0"
|
||||
thiserror = "1.0"
|
||||
|
@ -37,7 +37,7 @@ let cmdseq = vec![
|
||||
];
|
||||
|
||||
let fe = FeDevice::open_rw("/dev/dvb/adapter0/frontend0")?;
|
||||
fe.ioctl_set_property(&cmdseq)?;
|
||||
fe.set_properties(&cmdseq)?;
|
||||
```
|
||||
|
||||
Frontend information:
|
||||
|
@ -97,7 +97,7 @@ impl CaDevice {
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.custom_flags(::libc::O_NONBLOCK)
|
||||
.custom_flags(::nix::libc::O_NONBLOCK)
|
||||
.open(path)
|
||||
.with_context(|| format!("CA: failed to open device {}", path.display()))?;
|
||||
|
||||
|
164
src/fe/mod.rs
164
src/fe/mod.rs
@ -9,10 +9,8 @@ use {
|
||||
fs::{
|
||||
File,
|
||||
OpenOptions,
|
||||
read_to_string,
|
||||
},
|
||||
ops::Range,
|
||||
os::linux::fs::MetadataExt,
|
||||
os::unix::{
|
||||
fs::{
|
||||
OpenOptionsExt,
|
||||
@ -23,10 +21,7 @@ use {
|
||||
RawFd,
|
||||
},
|
||||
},
|
||||
path::{
|
||||
Path,
|
||||
PathBuf,
|
||||
},
|
||||
path::Path,
|
||||
},
|
||||
|
||||
anyhow::{
|
||||
@ -35,9 +30,9 @@ use {
|
||||
},
|
||||
thiserror::Error,
|
||||
|
||||
crate::ioctl::{
|
||||
ioctl,
|
||||
IoctlInt,
|
||||
nix::{
|
||||
ioctl_read,
|
||||
ioctl_write_ptr,
|
||||
},
|
||||
|
||||
sys::*,
|
||||
@ -88,18 +83,13 @@ pub struct FeDevice {
|
||||
frequency_range: Range<u32>,
|
||||
symbolrate_range: Range<u32>,
|
||||
caps: u32,
|
||||
|
||||
vendor_id: u16,
|
||||
model_id: u16,
|
||||
}
|
||||
|
||||
|
||||
impl fmt::Display for FeDevice {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "DVB API: {}.{}", self.api_version >> 8, self.api_version & 0xFF)?;
|
||||
|
||||
writeln!(f, "Device ID: {:04x}:{:04x}", self.vendor_id, self.model_id)?;
|
||||
writeln!(f, "Device Name: {}", self.name)?;
|
||||
writeln!(f, "Frontend: {}", self.name)?;
|
||||
|
||||
write!(f, "Delivery system:")?;
|
||||
for v in &self.delivery_system_list {
|
||||
@ -129,13 +119,6 @@ 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 cmdseq = [
|
||||
@ -143,12 +126,12 @@ impl FeDevice {
|
||||
DtvProperty::new(DTV_TONE, SEC_TONE_OFF),
|
||||
DtvProperty::new(DTV_CLEAR, 0),
|
||||
];
|
||||
self.ioctl_set_property(&cmdseq).context("fe clear")?;
|
||||
self.set_properties(&cmdseq).context("frontend clear")?;
|
||||
|
||||
let mut event = FeEvent::default();
|
||||
|
||||
for _ in 0 .. FE_MAX_EVENT {
|
||||
if self.ioctl(FE_GET_EVENT, event.as_mut_ptr()).is_err() {
|
||||
if self.get_event(&mut event).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -156,49 +139,13 @@ impl FeDevice {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_info_pci(&mut self, path: &mut PathBuf) -> Result<()> {
|
||||
path.push("vendor");
|
||||
let vendor = read_to_string(&path)?;
|
||||
path.pop();
|
||||
|
||||
let value = vendor.trim_end();
|
||||
if value.starts_with("0x") {
|
||||
self.vendor_id = u16::from_str_radix(&value[2 ..], 16).unwrap_or(0);
|
||||
}
|
||||
|
||||
path.push("device");
|
||||
let device = read_to_string(&path)?;
|
||||
path.pop();
|
||||
|
||||
let value = device.trim_end();
|
||||
if value.starts_with("0x") {
|
||||
self.model_id = u16::from_str_radix(&value[2 ..], 16).unwrap_or(0);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_info_usb(&mut self, path: &mut PathBuf) -> Result<()> {
|
||||
path.push("idVendor");
|
||||
let vendor = read_to_string(&path)?;
|
||||
path.pop();
|
||||
|
||||
let value = vendor.trim_end();
|
||||
self.vendor_id = u16::from_str_radix(value, 16).unwrap_or(0);
|
||||
|
||||
path.push("idProduct");
|
||||
let device = read_to_string(&path)?;
|
||||
path.pop();
|
||||
|
||||
let value = device.trim_end();
|
||||
self.model_id = u16::from_str_radix(value, 16).unwrap_or(0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_info(&mut self) -> Result<()> {
|
||||
let mut feinfo = FeInfo::default();
|
||||
self.ioctl(FE_GET_INFO, feinfo.as_mut_ptr()).context("fe get info")?;
|
||||
|
||||
ioctl_read!(#[inline] ioctl_call, b'o', 61, FeInfo);
|
||||
unsafe {
|
||||
ioctl_call(self.as_raw_fd(), &mut feinfo as *mut _)
|
||||
}.context("frontend get info")?;
|
||||
|
||||
if let Some(len) = feinfo.name.iter().position(|&b| b == 0) {
|
||||
let name = unsafe { CStr::from_ptr(feinfo.name[.. len + 1].as_ptr()) };
|
||||
@ -218,7 +165,7 @@ impl FeDevice {
|
||||
DtvProperty::new(DTV_API_VERSION, 0),
|
||||
DtvProperty::new(DTV_ENUM_DELSYS, 0),
|
||||
];
|
||||
self.ioctl_get_property(&mut cmdseq).context("fe get api version (deprecated driver)")?;
|
||||
self.get_properties(&mut cmdseq).context("frontend get api version (deprecated driver)")?;
|
||||
|
||||
// DVB API Version
|
||||
|
||||
@ -234,36 +181,13 @@ impl FeDevice {
|
||||
|
||||
// dev-file metadata
|
||||
|
||||
let metadata = self.file.metadata().context("fe get device metadata")?;
|
||||
let metadata = self.file.metadata().context("frontend get device metadata")?;
|
||||
|
||||
ensure!(
|
||||
metadata.file_type().is_char_device(),
|
||||
FeError::InvalidDeviceFormat
|
||||
);
|
||||
|
||||
let rdev = metadata.st_rdev();
|
||||
let major = unsafe { ::libc::major(rdev) };
|
||||
let minor = unsafe { ::libc::minor(rdev) };
|
||||
|
||||
let mut dev_path: PathBuf = format!("/sys/dev/char/{}:{}/device", major, minor).into();
|
||||
|
||||
// USB/PCI subsystem
|
||||
|
||||
dev_path.push("subsystem");
|
||||
let subsystem_path = dev_path.read_link().context("fe subsystem read link")?;
|
||||
dev_path.pop();
|
||||
|
||||
let subsystem = subsystem_path.file_name()
|
||||
.unwrap_or_default()
|
||||
.to_str()
|
||||
.unwrap_or_default();
|
||||
|
||||
match subsystem {
|
||||
"pci" => self.get_info_pci(&mut dev_path).context("fe get pci info")?,
|
||||
"usb" => self.get_info_usb(&mut dev_path).context("fe get usb info")?,
|
||||
_ => bail!(FeError::InvalidSubsystem),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -271,7 +195,7 @@ impl FeDevice {
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(w)
|
||||
.custom_flags(::libc::O_NONBLOCK)
|
||||
.custom_flags(::nix::libc::O_NONBLOCK)
|
||||
.open(path)
|
||||
.context("fe open")?;
|
||||
|
||||
@ -285,9 +209,6 @@ impl FeDevice {
|
||||
frequency_range: 0 .. 0,
|
||||
symbolrate_range: 0 .. 0,
|
||||
caps: 0,
|
||||
|
||||
vendor_id: 0,
|
||||
model_id: 0,
|
||||
};
|
||||
|
||||
fe.get_info()?;
|
||||
@ -303,7 +224,7 @@ impl FeDevice {
|
||||
#[inline]
|
||||
pub fn open_rw<P: AsRef<Path>>(path: P) -> Result<FeDevice> { Self::open(path, true) }
|
||||
|
||||
fn check_cmdseq(&self, cmdseq: &[DtvProperty]) -> Result<()> {
|
||||
fn check_properties(&self, cmdseq: &[DtvProperty]) -> Result<()> {
|
||||
for p in cmdseq {
|
||||
match p.cmd {
|
||||
DTV_FREQUENCY => {
|
||||
@ -366,26 +287,58 @@ impl FeDevice {
|
||||
}
|
||||
|
||||
/// Sets properties on frontend device
|
||||
pub fn ioctl_set_property(&self, cmdseq: &[DtvProperty]) -> Result<()> {
|
||||
self.check_cmdseq(cmdseq).context("fe property check")?;
|
||||
pub fn set_properties(&self, cmdseq: &[DtvProperty]) -> Result<()> {
|
||||
self.check_properties(cmdseq).context("fe property check")?;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DtvProperties {
|
||||
num: u32,
|
||||
props: *const DtvProperty,
|
||||
}
|
||||
|
||||
let cmd = DtvProperties {
|
||||
num: cmdseq.len() as u32,
|
||||
props: cmdseq.as_ptr(),
|
||||
};
|
||||
|
||||
self.ioctl(FE_SET_PROPERTY, cmd.as_ptr())
|
||||
ioctl_write_ptr!(#[inline] ioctl_call, b'o', 82, DtvProperties);
|
||||
unsafe {
|
||||
ioctl_call(self.as_raw_fd(), &cmd as *const _)
|
||||
}.context("frontend set properties")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets properties from frontend device
|
||||
pub fn ioctl_get_property(&self, cmdseq: &mut [DtvProperty]) -> Result<()> {
|
||||
pub fn get_properties(&self, cmdseq: &mut [DtvProperty]) -> Result<()> {
|
||||
#[repr(C)]
|
||||
pub struct DtvProperties {
|
||||
num: u32,
|
||||
props: *mut DtvProperty,
|
||||
}
|
||||
|
||||
let mut cmd = DtvPropertiesMut {
|
||||
let mut cmd = DtvProperties {
|
||||
num: cmdseq.len() as u32,
|
||||
props: cmdseq.as_mut_ptr(),
|
||||
};
|
||||
|
||||
self.ioctl(FE_GET_PROPERTY, cmd.as_mut_ptr())
|
||||
ioctl_read!(#[inline] ioctl_call, b'o', 83, DtvProperties);
|
||||
unsafe {
|
||||
ioctl_call(self.as_raw_fd(), &mut cmd as *mut _)
|
||||
}.context("frontend get properties")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns a frontend events if available
|
||||
pub fn get_event(&self, event: &mut FeEvent) -> Result<()> {
|
||||
ioctl_read!(#[inline] ioctl_call, b'o', 78, FeEvent);
|
||||
|
||||
unsafe {
|
||||
ioctl_call(self.as_raw_fd(), event as *mut _)
|
||||
}.context("frontend get event")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets DiSEqC master command
|
||||
@ -406,14 +359,19 @@ impl FeDevice {
|
||||
/// - 00x0 - bit is set on SEC_VOLTAGE_18
|
||||
/// - 000x - bit is set on SEC_TONE_ON
|
||||
///
|
||||
pub fn ioctl_diseqc_master_cmd(&self, msg: &[u8]) -> Result<()> {
|
||||
pub fn diseqc_master_cmd(&self, msg: &[u8]) -> Result<()> {
|
||||
let mut cmd = DiseqcMasterCmd::default();
|
||||
debug_assert!(msg.len() <= cmd.msg.len());
|
||||
|
||||
cmd.msg[0 .. msg.len()].copy_from_slice(msg);
|
||||
cmd.len = msg.len() as u8;
|
||||
|
||||
self.ioctl(FE_DISEQC_SEND_MASTER_CMD, cmd.as_ptr())
|
||||
ioctl_write_ptr!(ioctl_call, b'o', 63, DiseqcMasterCmd);
|
||||
unsafe {
|
||||
ioctl_call(self.as_raw_fd(), &cmd as *const _)
|
||||
}.context("frontend diseqc master cmd")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the current API version
|
||||
|
@ -1,7 +1,17 @@
|
||||
use {
|
||||
std::fmt,
|
||||
std::{
|
||||
fmt,
|
||||
os::unix::io::AsRawFd,
|
||||
},
|
||||
|
||||
anyhow::Result,
|
||||
anyhow::{
|
||||
Context,
|
||||
Result,
|
||||
},
|
||||
|
||||
nix::{
|
||||
ioctl_read,
|
||||
},
|
||||
|
||||
super::{
|
||||
FeDevice,
|
||||
@ -199,7 +209,11 @@ impl FeStatus {
|
||||
/// 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 _)?;
|
||||
|
||||
ioctl_read!(#[inline] ioctl_call, b'o', 69, u32);
|
||||
unsafe {
|
||||
ioctl_call(fe.as_raw_fd(), &mut self.status as *mut _)
|
||||
}.context("frontend read status")?;
|
||||
|
||||
if self.status == FE_NONE {
|
||||
return Ok(());
|
||||
@ -211,7 +225,7 @@ impl FeStatus {
|
||||
DtvProperty::new(DTV_STAT_PRE_ERROR_BIT_COUNT, 0),
|
||||
DtvProperty::new(DTV_STAT_ERROR_BLOCK_COUNT, 0),
|
||||
];
|
||||
fe.ioctl_get_property(&mut cmdseq)?;
|
||||
fe.get_properties(&mut cmdseq)?;
|
||||
|
||||
self.signal = (unsafe { cmdseq[0].u.st }).get_decibel();
|
||||
self.snr = (unsafe { cmdseq[1].u.st }).get_decibel();
|
||||
|
@ -8,7 +8,6 @@ use {
|
||||
IoctlInt,
|
||||
io_none,
|
||||
io_read,
|
||||
io_write,
|
||||
},
|
||||
};
|
||||
|
||||
@ -175,12 +174,6 @@ impl Default for DiseqcMasterCmd {
|
||||
}
|
||||
|
||||
|
||||
impl DiseqcMasterCmd {
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const DiseqcMasterCmd { self as *const _ }
|
||||
}
|
||||
|
||||
|
||||
/// DiSEqC received data
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
@ -708,35 +701,6 @@ pub const DTV_MAX_COMMAND: u32 = DTV_INPUT;
|
||||
pub const DTV_IOCTL_MAX_MSGS: usize = 64;
|
||||
|
||||
|
||||
/// a set of command/value pairs for FE_SET_PROPERTY
|
||||
#[repr(C)]
|
||||
pub struct DtvProperties {
|
||||
pub num: u32,
|
||||
pub props: *const DtvProperty,
|
||||
}
|
||||
|
||||
|
||||
impl DtvProperties {
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const DtvProperties { self as *const _ }
|
||||
}
|
||||
|
||||
|
||||
// a set of command/value pairs for FE_GET_PROPERTY
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct DtvPropertiesMut {
|
||||
pub num: u32,
|
||||
pub props: *mut DtvProperty,
|
||||
}
|
||||
|
||||
|
||||
impl DtvPropertiesMut {
|
||||
#[inline]
|
||||
pub fn as_mut_ptr(&mut self) -> *mut DtvPropertiesMut { self as *mut _ }
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct FeParameters {
|
||||
@ -772,10 +736,7 @@ impl FeEvent {
|
||||
}
|
||||
|
||||
|
||||
pub const FE_GET_INFO: IoctlInt = io_read::<FeInfo>(b'o', 61);
|
||||
|
||||
pub const FE_DISEQC_RESET_OVERLOAD: IoctlInt = io_none(b'o', 62);
|
||||
pub const FE_DISEQC_SEND_MASTER_CMD: IoctlInt = io_write::<DiseqcMasterCmd>(b'o', 63);
|
||||
pub const FE_DISEQC_RECV_SLAVE_REPLY: IoctlInt = io_read::<DiseqcSlaveReply>(b'o', 64);
|
||||
pub const FE_DISEQC_SEND_BURST: IoctlInt = io_none(b'o', 65);
|
||||
|
||||
@ -783,14 +744,9 @@ pub const FE_SET_TONE: IoctlInt = io_none(b'o', 66);
|
||||
pub const FE_SET_VOLTAGE: IoctlInt = io_none(b'o', 67);
|
||||
pub const FE_ENABLE_HIGH_LNB_VOLTAGE: IoctlInt = io_none(b'o', 68);
|
||||
|
||||
pub const FE_READ_STATUS: IoctlInt = io_read::<u32>(b'o', 69);
|
||||
pub const FE_READ_BER: IoctlInt = io_read::<u32>(b'o', 70);
|
||||
pub const FE_READ_SIGNAL_STRENGTH: IoctlInt = io_read::<u16>(b'o', 71);
|
||||
pub const FE_READ_SNR: IoctlInt = io_read::<u16>(b'o', 72);
|
||||
pub const FE_READ_UNCORRECTED_BLOCKS: IoctlInt = io_read::<u32>(b'o', 73);
|
||||
|
||||
pub const FE_GET_EVENT: IoctlInt = io_read::<FeEvent>(b'o', 78);
|
||||
pub const FE_SET_FRONTEND_TUNE_MODE: IoctlInt = io_none(b'o', 81);
|
||||
|
||||
pub const FE_SET_PROPERTY: IoctlInt = io_write::<DtvProperties>(b'o', 82);
|
||||
pub const FE_GET_PROPERTY: IoctlInt = io_read::<DtvPropertiesMut>(b'o', 83);
|
||||
|
Loading…
Reference in New Issue
Block a user