From 1f0bee854c79c2db157ad4ad73e82a30b07cfd3b Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Wed, 6 Sep 2023 23:44:21 +0200 Subject: [PATCH] device: Use `OwnedFd` type and bump MSRV to 1.66 The first new commit 22a2365 on `next` switches to the `RawFd` type from the `std::os::fd` module which is only available since Rust 1.66. This module also provides an `OwnedFd` type which already has a `close()` call in the `Drop` implementation, and implements the desired `AsRawFd` (and `AsFd` and `IntoRawFd`) traits. Note that these types were already stabilized in Rust 1.63 under `std::os::unix::io`, which is now merely a reexport of `std::os::fd`. This also replaces the forgotten `.fd()` calls with `.as_raw_fd()` from from commit 17c2871. --- Cargo.toml | 1 + src/device.rs | 73 ++++++++++++++++++++++++---------------- src/io/mod.rs | 19 ++++++----- src/video/capture/mod.rs | 4 +-- src/video/mod.rs | 12 +++---- src/video/output/mod.rs | 4 +-- 6 files changed, 65 insertions(+), 48 deletions(-) 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..824be6e 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, )?; @@ -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 d9688a6..f5ff59e 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -3,6 +3,7 @@ use std::{ marker::PhantomData, mem, ops::{Index, IndexMut}, + os::fd::AsRawFd, ptr, slice, sync::Arc, }; @@ -65,7 +66,7 @@ impl Queue { unsafe { v4l2::ioctl( - self.handle.fd(), + self.handle.as_raw_fd(), v4l2::vidioc::VIDIOC_REQBUFS, &mut v4l2_reqbufs as *mut _ as *mut std::os::raw::c_void, )?; @@ -88,7 +89,7 @@ impl Queue { unsafe { v4l2::ioctl( - self.handle.fd(), + self.handle.as_raw_fd(), v4l2::vidioc::VIDIOC_QUERYBUF, &mut buf as *mut _ as *mut std::os::raw::c_void, )?; @@ -101,7 +102,7 @@ impl Queue { fn streamon(&mut self) -> io::Result<()> { unsafe { v4l2::ioctl( - self.handle.fd(), + self.handle.as_raw_fd(), v4l2::vidioc::VIDIOC_STREAMON, &mut self.buf_type as *mut _ as *mut std::os::raw::c_void, ) @@ -112,7 +113,7 @@ impl Queue { fn streamoff(&mut self) -> io::Result<()> { unsafe { v4l2::ioctl( - self.handle.fd(), + self.handle.as_raw_fd(), v4l2::vidioc::VIDIOC_STREAMOFF, &mut self.buf_type as *mut _ as *mut std::os::raw::c_void, ) @@ -125,7 +126,7 @@ impl Queue { unsafe { v4l2::ioctl( - self.handle.fd(), + self.handle.as_raw_fd(), v4l2::vidioc::VIDIOC_QBUF, buf as *mut _ as *mut std::os::raw::c_void, ) @@ -138,7 +139,7 @@ impl Queue { unsafe { v4l2::ioctl( - self.handle.fd(), + self.handle.as_raw_fd(), v4l2::vidioc::VIDIOC_DQBUF, buf as *mut _ as *mut std::os::raw::c_void, ) @@ -244,7 +245,7 @@ impl Queue, queue::Idle> { let mapping = unsafe { v4l2::ioctl( - queue.handle.fd(), + queue.handle.as_raw_fd(), v4l2::vidioc::VIDIOC_QUERYBUF, &mut v4l2_buf as *mut _ as *mut std::os::raw::c_void, )?; @@ -254,7 +255,7 @@ impl Queue, queue::Idle> { v4l2_buf.length as usize, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_SHARED, - queue.handle.fd(), + queue.handle.as_raw_fd(), v4l2_buf.m.offset as libc::off_t, )?; @@ -322,7 +323,7 @@ impl Queue { }; unsafe { v4l2::ioctl( - queue.handle.fd(), + queue.handle.as_raw_fd(), v4l2::vidioc::VIDIOC_G_FMT, &mut v4l2_fmt as *mut _ as *mut std::os::raw::c_void, )?; 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, )?;