Skip to main content

linux_media/
media_device_info.rs

1use std::ffi::CStr;
2use std::fmt;
3use std::fs::OpenOptions;
4use std::os::fd::{AsFd, AsRawFd, OwnedFd};
5use std::os::unix::fs::OpenOptionsExt;
6use std::path::Path;
7
8use linux_media_sys as media;
9use serde::{Deserialize, Serialize};
10
11use crate::error;
12use crate::ioctl;
13use crate::version::*;
14
15#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
16pub struct MediaDeviceInfo {
17    pub driver: String,
18    pub model: String,
19    pub serial: String,
20    pub bus_info: String,
21    pub media_version: Version,
22    pub hw_revision: u32,
23    pub driver_version: Version,
24}
25
26impl fmt::Debug for MediaDeviceInfo {
27    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28        write!(
29            f,
30            "MediaDeviceInfo {{ driver: \"{}\", model: \"{}\", serial: \"{}\", bus_info: \"{}\", media_version: {}, hw_revision: 0x{:02X}, driver_version: {} }}",
31            self.driver,
32            self.model,
33            self.serial,
34            self.bus_info,
35            self.media_version,
36            self.hw_revision,
37            self.driver_version,
38        )
39    }
40}
41
42impl MediaDeviceInfo {
43    pub fn from_path<P>(path: P) -> error::Result<(OwnedFd, Self)>
44    where
45        P: AsRef<Path>,
46    {
47        let path = path.as_ref();
48        let fd: OwnedFd = OpenOptions::new()
49            .read(true)
50            .write(true)
51            .custom_flags(libc::O_CLOEXEC)
52            .open(path)
53            .map_err(|err| error::trap_io_error(err, path.to_path_buf()))?
54            .into();
55        let info = Self::from_fd(fd.as_fd())?;
56        Ok((fd, info))
57    }
58
59    pub fn from_fd<F>(fd: F) -> error::Result<Self>
60    where
61        F: AsFd,
62    {
63        let info = unsafe {
64            let mut info: media::media_device_info = std::mem::zeroed();
65            ioctl!(fd.as_fd(), media::MEDIA_IOC_DEVICE_INFO, &mut info)?;
66            info
67        };
68        Ok(info.into())
69    }
70
71    pub fn driver(&self) -> &str {
72        &self.driver
73    }
74
75    pub fn model(&self) -> &str {
76        &self.model
77    }
78
79    pub fn serial(&self) -> &str {
80        &self.serial
81    }
82
83    pub fn bus_info(&self) -> &str {
84        &self.bus_info
85    }
86
87    pub fn media_version(&self) -> Version {
88        self.media_version.clone()
89    }
90
91    pub fn hw_revision(&self) -> u32 {
92        self.hw_revision
93    }
94
95    pub fn driver_version(&self) -> Version {
96        self.driver_version.clone()
97    }
98}
99
100impl From<media::media_device_info> for MediaDeviceInfo {
101    fn from(info: media::media_device_info) -> Self {
102        let driver = unsafe { CStr::from_ptr(info.driver.as_ptr()) }
103            .to_string_lossy()
104            .to_string();
105        let model = unsafe { CStr::from_ptr(info.model.as_ptr()) }
106            .to_string_lossy()
107            .to_string();
108        let serial = unsafe { CStr::from_ptr(info.serial.as_ptr()) }
109            .to_string_lossy()
110            .to_string();
111        let bus_info = unsafe { CStr::from_ptr(info.bus_info.as_ptr()) }
112            .to_string_lossy()
113            .to_string();
114        let media_version = info.media_version.into();
115        let hw_revision = info.hw_revision;
116        let driver_version = info.driver_version.into();
117        Self {
118            driver,
119            model,
120            serial,
121            bus_info,
122            media_version,
123            hw_revision,
124            driver_version,
125        }
126    }
127}