diff --git a/Cargo.toml b/Cargo.toml index bb3fd17..28da8b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" license = "MIT" readme = "README.md" repository= "https://github.com/raymanfx/libv4l-rs" +rust-version = "1.66" [dependencies] bitflags = "1.2.1" diff --git a/src/device.rs b/src/device.rs index 93dc90a..34582a5 100644 --- a/src/device.rs +++ b/src/device.rs @@ -1,8 +1,8 @@ -use std::convert::TryFrom; -use std::path::Path; use std::{ + convert::TryFrom, io, mem, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, + path::Path, sync::Arc, }; @@ -72,7 +72,7 @@ impl Device { unsafe { let mut v4l2_caps: v4l2_capability = mem::zeroed(); v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_QUERYCAP, &mut v4l2_caps as *mut _ as *mut std::os::raw::c_void, )?; @@ -91,7 +91,7 @@ impl Device { v4l2_ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; v4l2_ctrl.id |= V4L2_CTRL_FLAG_NEXT_COMPOUND; match v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_QUERY_EXT_CTRL, &mut v4l2_ctrl as *mut _ as *mut std::os::raw::c_void, ) { @@ -114,7 +114,7 @@ impl Device { ..mem::zeroed() }; let res = v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_QUERYMENU, &mut v4l2_menu as *mut _ as *mut std::os::raw::c_void, ); @@ -169,7 +169,7 @@ impl Device { ..mem::zeroed() }; v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_QUERY_EXT_CTRL, &mut queryctrl as *mut _ as *mut std::os::raw::c_void, )?; @@ -188,7 +188,7 @@ impl Device { ..mem::zeroed() }; v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_G_EXT_CTRLS, &mut v4l2_ctrls as *mut _ as *mut std::os::raw::c_void, )?; @@ -276,19 +276,19 @@ impl Device { } control::Value::CompoundU8(ref val) => { control.__bindgen_anon_1.p_u8 = val.as_ptr() as *mut u8; - control.size = (val.len() * std::mem::size_of::()) as u32; + control.size = std::mem::size_of_val(val.as_slice()) as u32; } control::Value::CompoundU16(ref val) => { control.__bindgen_anon_1.p_u16 = val.as_ptr() as *mut u16; - control.size = (val.len() * std::mem::size_of::()) as u32; + control.size = std::mem::size_of_val(val.as_slice()) as u32; } control::Value::CompoundU32(ref val) => { control.__bindgen_anon_1.p_u32 = val.as_ptr() as *mut u32; - control.size = (val.len() * std::mem::size_of::()) as u32; + control.size = std::mem::size_of_val(val.as_slice()) as u32; } control::Value::CompoundPtr(ref val) => { control.__bindgen_anon_1.ptr = val.as_ptr() as *mut std::os::raw::c_void; - control.size = (val.len() * std::mem::size_of::()) as u32; + control.size = std::mem::size_of_val(val.as_slice()) as u32; } }; @@ -311,7 +311,7 @@ impl Device { }; v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_S_EXT_CTRLS, &mut controls as *mut _ as *mut std::os::raw::c_void, ) @@ -323,7 +323,7 @@ impl io::Read for Device { fn read(&mut self, buf: &mut [u8]) -> io::Result { unsafe { let ret = libc::read( - self.handle().as_raw_fd(), + self.as_raw_fd(), buf.as_mut_ptr() as *mut std::os::raw::c_void, buf.len(), ); @@ -339,7 +339,7 @@ impl io::Write for Device { fn write(&mut self, buf: &[u8]) -> io::Result { unsafe { let ret = libc::write( - self.handle().as_raw_fd(), + self.as_raw_fd(), buf.as_ptr() as *const std::os::raw::c_void, buf.len(), ); @@ -358,17 +358,29 @@ impl io::Write for Device { } } +impl AsFd for Device { + fn as_fd(&self) -> BorrowedFd<'_> { + self.handle.as_fd() + } +} + +impl AsRawFd for Device { + fn as_raw_fd(&self) -> RawFd { + self.handle.as_raw_fd() + } +} + /// Device handle for low-level access. /// /// Acquiring a handle facilitates (possibly mutating) interactions with the device. -#[derive(Debug, Clone)] -pub struct Handle(RawFd); +#[derive(Debug)] +pub struct Handle(OwnedFd); impl Handle { /// Wraps an existing file descriptor /// /// The caller must ensure that `fd` is a valid, open file descriptor for a V4L device. - pub unsafe fn new(fd: RawFd) -> Self { + pub fn new(fd: OwnedFd) -> Self { Self(fd) } @@ -385,7 +397,7 @@ impl Handle { return Err(io::Error::last_os_error()); } - Ok(Handle(fd)) + Ok(Handle(unsafe { OwnedFd::from_raw_fd(fd) })) } /// Polls the file descriptor for I/O events @@ -400,35 +412,38 @@ impl Handle { pub fn poll(&self, events: i16, timeout: i32) -> io::Result { match unsafe { libc::poll( - [libc::pollfd { - fd: self.0, + &mut libc::pollfd { + fd: self.as_raw_fd(), events, revents: 0, - }] - .as_mut_ptr(), + }, 1, timeout, ) } { -1 => Err(io::Error::last_os_error()), - ret => { - // A return value of zero means that we timed out. A positive value signifies the - // number of fds with non-zero revents fields (aka I/O activity). - assert!(ret == 0 || ret == 1); - Ok(ret) - } + // A return value of zero means that we timed out. A positive value signifies the + // number of fds with non-zero revents fields (aka I/O activity). + ret @ 0..=1 => Ok(ret), + ret => panic!("Invalid return value {}", ret), } } } -impl Drop for Handle { - fn drop(&mut self) { - let _ = v4l2::close(self.0); +impl AsFd for Handle { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() } } impl AsRawFd for Handle { fn as_raw_fd(&self) -> RawFd { - self.0 + self.0.as_raw_fd() + } +} + +impl IntoRawFd for Handle { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() } } diff --git a/src/io/mod.rs b/src/io/mod.rs index dd35dbe..7747776 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -3,7 +3,7 @@ use std::{ marker::PhantomData, mem, ops::{Index, IndexMut}, - os::unix::io::AsRawFd, + os::fd::AsRawFd, ptr, slice, sync::Arc, }; diff --git a/src/video/capture/mod.rs b/src/video/capture/mod.rs index 05edf29..4a01209 100644 --- a/src/video/capture/mod.rs +++ b/src/video/capture/mod.rs @@ -45,7 +45,7 @@ impl Capture for Device { ..mem::zeroed() }; v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_G_PARM, &mut v4l2_params as *mut _ as *mut std::os::raw::c_void, )?; @@ -63,7 +63,7 @@ impl Capture for Device { }, }; v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_S_PARM, &mut v4l2_params as *mut _ as *mut std::os::raw::c_void, )?; diff --git a/src/video/mod.rs b/src/video/mod.rs index a51e21a..b5927f3 100644 --- a/src/video/mod.rs +++ b/src/video/mod.rs @@ -32,7 +32,7 @@ impl traits::Video for Device { loop { let ret = unsafe { v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_ENUM_FRAMEINTERVALS, &mut v4l2_struct as *mut _ as *mut std::os::raw::c_void, ) @@ -65,7 +65,7 @@ impl traits::Video for Device { loop { let ret = unsafe { v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_ENUM_FRAMESIZES, &mut v4l2_struct as *mut _ as *mut std::os::raw::c_void, ) @@ -99,7 +99,7 @@ impl traits::Video for Device { unsafe { ret = v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_ENUM_FMT, &mut v4l2_fmt as *mut _ as *mut std::os::raw::c_void, ); @@ -121,7 +121,7 @@ impl traits::Video for Device { unsafe { ret = v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_ENUM_FMT, &mut v4l2_fmt as *mut _ as *mut std::os::raw::c_void, ); @@ -138,7 +138,7 @@ impl traits::Video for Device { ..mem::zeroed() }; v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_G_FMT, &mut v4l2_fmt as *mut _ as *mut std::os::raw::c_void, )?; @@ -154,7 +154,7 @@ impl traits::Video for Device { fmt: v4l2_format__bindgen_ty_1 { pix: (*fmt).into() }, }; v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_S_FMT, &mut v4l2_fmt as *mut _ as *mut std::os::raw::c_void, )?; diff --git a/src/video/output/mod.rs b/src/video/output/mod.rs index 27c3d07..8f2406b 100644 --- a/src/video/output/mod.rs +++ b/src/video/output/mod.rs @@ -45,7 +45,7 @@ impl Output for Device { ..mem::zeroed() }; v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_G_PARM, &mut v4l2_params as *mut _ as *mut std::os::raw::c_void, )?; @@ -63,7 +63,7 @@ impl Output for Device { }, }; v4l2::ioctl( - self.handle().as_raw_fd(), + self.as_raw_fd(), v4l2::vidioc::VIDIOC_S_PARM, &mut v4l2_params as *mut _ as *mut std::os::raw::c_void, )?;