use crate::ioctl;
use crate::util;
use crate::Media;
use core::ffi::CStr;
use core::fmt;
use nix::errno::Errno;
use nix::libc::c_char;
use std::os::fd::AsRawFd;
#[repr(C)]
pub struct DeviceInfo {
driver: [c_char; 16],
model: [c_char; 32],
serial: [c_char; 40],
bus_info: [c_char; 32],
media_version: u32,
hw_revision: u32,
driver_version: u32,
reserved: [u32; 31],
}
impl fmt::Debug for DeviceInfo {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("DeviceInfo")
.field("driver", &self.driver())
.field("model", &self.model())
.field("serial", &self.serial())
.field("bus_info", &self.bus_info())
.field("media_version", &self.media_version())
.field("hw_revision", &self.hw_revision)
.field("driver_version", &self.driver_version())
.finish()
}
}
impl Default for DeviceInfo {
fn default() -> DeviceInfo {
DeviceInfo {
driver: [0; 16],
model: [0; 32],
serial: [0; 40],
bus_info: [0; 32],
media_version: 0,
hw_revision: 0,
driver_version: 0,
reserved: [0; 31],
}
}
}
impl DeviceInfo {
pub(crate) fn from_media(media: &Media) -> Result<DeviceInfo, Errno> {
let mut data = DeviceInfo::default();
unsafe { ioctl::device_info(media.as_raw_fd(), &mut data) }?;
Ok(data)
}
pub fn driver(&self) -> &str {
unsafe {
let c_str = CStr::from_ptr(self.driver.as_ptr());
std::str::from_utf8_unchecked(c_str.to_bytes())
}
}
pub fn model(&self) -> &str {
unsafe {
let c_str = CStr::from_ptr(self.model.as_ptr());
std::str::from_utf8_unchecked(c_str.to_bytes())
}
}
pub fn serial(&self) -> &str {
unsafe {
let c_str = CStr::from_ptr(self.serial.as_ptr());
std::str::from_utf8_unchecked(c_str.to_bytes())
}
}
pub fn bus_info(&self) -> &str {
unsafe {
let c_str = CStr::from_ptr(self.bus_info.as_ptr());
std::str::from_utf8_unchecked(c_str.to_bytes())
}
}
pub fn media_version(&self) -> String {
util::format_kernel_version(self.media_version)
}
pub fn hw_revision(&self) -> u32 {
self.hw_revision
}
pub fn driver_version(&self) -> String {
util::format_kernel_version(self.driver_version)
}
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! assert_size (
($t:ty, $sz:expr) => (
assert_eq!(::std::mem::size_of::<$t>(), $sz);
);
);
#[test]
fn size() {
assert_size!(DeviceInfo, 256);
}
}