diff --git a/drm-ffi/src/gem.rs b/drm-ffi/src/gem.rs index 79e87ce..4d330d6 100644 --- a/drm-ffi/src/gem.rs +++ b/drm-ffi/src/gem.rs @@ -5,12 +5,13 @@ use crate::ioctl; use drm_sys::*; -use crate::result::SystemError as Error; - -use std::os::unix::io::{AsRawFd, BorrowedFd}; +use std::{ + io, + os::unix::io::{AsRawFd, BorrowedFd}, +}; /// Open a GEM object given it's 32-bit name, returning the handle. -pub fn open(fd: BorrowedFd<'_>, name: u32) -> Result { +pub fn open(fd: BorrowedFd<'_>, name: u32) -> io::Result { let mut gem = drm_gem_open { name, ..Default::default() @@ -24,7 +25,7 @@ pub fn open(fd: BorrowedFd<'_>, name: u32) -> Result { } /// Closes a GEM object given it's handle. -pub fn close(fd: BorrowedFd<'_>, handle: u32) -> Result { +pub fn close(fd: BorrowedFd<'_>, handle: u32) -> io::Result { let gem = drm_gem_close { handle, ..Default::default() @@ -38,11 +39,7 @@ pub fn close(fd: BorrowedFd<'_>, handle: u32) -> Result { } /// Converts a GEM object's handle to a PRIME file descriptor. -pub fn handle_to_fd( - fd: BorrowedFd<'_>, - handle: u32, - flags: u32, -) -> Result { +pub fn handle_to_fd(fd: BorrowedFd<'_>, handle: u32, flags: u32) -> io::Result { let mut prime = drm_prime_handle { handle, flags, @@ -57,10 +54,7 @@ pub fn handle_to_fd( } /// Converts a PRIME file descriptor to a GEM object's handle. -pub fn fd_to_handle( - fd: BorrowedFd<'_>, - primefd: BorrowedFd<'_>, -) -> Result { +pub fn fd_to_handle(fd: BorrowedFd<'_>, primefd: BorrowedFd<'_>) -> io::Result { let mut prime = drm_prime_handle { fd: primefd.as_raw_fd(), ..Default::default() diff --git a/drm-ffi/src/lib.rs b/drm-ffi/src/lib.rs index 01f977d..c63c955 100644 --- a/drm-ffi/src/lib.rs +++ b/drm-ffi/src/lib.rs @@ -13,15 +13,16 @@ extern crate nix; #[macro_use] pub(crate) mod utils; -use crate::result::SystemError as Error; pub mod gem; mod ioctl; pub mod mode; -pub mod result; pub mod syncobj; use nix::libc::{c_int, c_ulong}; -use std::os::unix::io::{AsRawFd, BorrowedFd}; +use std::{ + io, + os::unix::io::{AsRawFd, BorrowedFd}, +}; /// /// Bindings to the methods of authentication the DRM provides. @@ -30,11 +31,13 @@ pub mod auth { use crate::ioctl; use drm_sys::*; - use nix::Error; - use std::os::unix::io::{AsRawFd, BorrowedFd}; + use std::{ + io, + os::unix::io::{AsRawFd, BorrowedFd}, + }; /// Get the 'Magic Authentication Token' for this file descriptor. - pub fn get_magic_token(fd: BorrowedFd<'_>) -> Result { + pub fn get_magic_token(fd: BorrowedFd<'_>) -> io::Result { let mut auth = drm_auth::default(); unsafe { @@ -45,7 +48,7 @@ pub mod auth { } /// Authorize another process' 'Magic Authentication Token'. - pub fn auth_magic_token(fd: BorrowedFd<'_>, auth: u32) -> Result { + pub fn auth_magic_token(fd: BorrowedFd<'_>, auth: u32) -> io::Result { let token = drm_auth { magic: auth }; unsafe { @@ -56,7 +59,7 @@ pub mod auth { } /// Acquire the 'Master DRM Lock' for this file descriptor. - pub fn acquire_master(fd: BorrowedFd<'_>) -> Result<(), Error> { + pub fn acquire_master(fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { ioctl::acquire_master(fd.as_raw_fd())?; } @@ -65,7 +68,7 @@ pub mod auth { } /// Release the 'Master DRM Lock' for this file descriptor. - pub fn release_master(fd: BorrowedFd<'_>) -> Result<(), Error> { + pub fn release_master(fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { ioctl::release_master(fd.as_raw_fd())?; } @@ -75,7 +78,7 @@ pub mod auth { } /// Load this device's Bus ID into a buffer. -pub fn get_bus_id(fd: BorrowedFd<'_>, mut buf: Option<&mut Vec>) -> Result { +pub fn get_bus_id(fd: BorrowedFd<'_>, mut buf: Option<&mut Vec>) -> io::Result { let mut sizes = drm_unique::default(); unsafe { ioctl::get_bus_id(fd.as_raw_fd(), &mut sizes)?; @@ -107,7 +110,7 @@ pub fn get_interrupt_from_bus_id( bus: c_int, dev: c_int, func: c_int, -) -> Result { +) -> io::Result { let mut irq = drm_irq_busid { busnum: bus, devnum: dev, @@ -123,7 +126,7 @@ pub fn get_interrupt_from_bus_id( } /// Get client information given a client's ID. -pub fn get_client(fd: BorrowedFd<'_>, idx: c_int) -> Result { +pub fn get_client(fd: BorrowedFd<'_>, idx: c_int) -> io::Result { let mut client = drm_client { idx, ..Default::default() @@ -137,7 +140,7 @@ pub fn get_client(fd: BorrowedFd<'_>, idx: c_int) -> Result { } /// Check if a capability is set. -pub fn get_capability(fd: BorrowedFd<'_>, cty: u64) -> Result { +pub fn get_capability(fd: BorrowedFd<'_>, cty: u64) -> io::Result { let mut cap = drm_get_cap { capability: cty, ..Default::default() @@ -151,11 +154,7 @@ pub fn get_capability(fd: BorrowedFd<'_>, cty: u64) -> Result, - cty: u64, - val: bool, -) -> Result { +pub fn set_capability(fd: BorrowedFd<'_>, cty: u64, val: bool) -> io::Result { let cap = drm_set_client_cap { capability: cty, value: val as u64, @@ -174,7 +173,7 @@ pub fn get_version( mut name_buf: Option<&mut Vec>, mut date_buf: Option<&mut Vec>, mut desc_buf: Option<&mut Vec>, -) -> Result { +) -> io::Result { let mut sizes = drm_version::default(); unsafe { ioctl::get_version(fd.as_raw_fd(), &mut sizes)?; @@ -211,7 +210,7 @@ pub fn wait_vblank( type_: u32, sequence: u32, signal: usize, -) -> Result { +) -> io::Result { // We can't assume the kernel will completely fill the reply in the union // with valid data (it won't populate the timestamp if the event flag is // set, for example), so use `default` to ensure the structure is completely diff --git a/drm-ffi/src/mode.rs b/drm-ffi/src/mode.rs index d95ba1c..49c2d5a 100644 --- a/drm-ffi/src/mode.rs +++ b/drm-ffi/src/mode.rs @@ -7,8 +7,10 @@ use crate::ioctl; use drm_sys::*; -use crate::result::SystemError as Error; -use std::os::unix::io::{AsRawFd, BorrowedFd}; +use std::{ + io, + os::unix::io::{AsRawFd, BorrowedFd}, +}; /// Enumerate most card resources. pub fn get_resources( @@ -17,7 +19,7 @@ pub fn get_resources( mut crtcs: Option<&mut Vec>, mut connectors: Option<&mut Vec>, mut encoders: Option<&mut Vec>, -) -> Result { +) -> io::Result { let mut sizes = drm_mode_card_res::default(); unsafe { ioctl::mode::get_resources(fd.as_raw_fd(), &mut sizes)?; @@ -56,7 +58,7 @@ pub fn get_resources( pub fn get_plane_resources( fd: BorrowedFd<'_>, mut planes: Option<&mut Vec>, -) -> Result { +) -> io::Result { let mut sizes = drm_mode_get_plane_res::default(); unsafe { ioctl::mode::get_plane_resources(fd.as_raw_fd(), &mut sizes)?; @@ -83,7 +85,7 @@ pub fn get_plane_resources( } /// Get info about a framebuffer. -pub fn get_framebuffer(fd: BorrowedFd<'_>, fb_id: u32) -> Result { +pub fn get_framebuffer(fd: BorrowedFd<'_>, fb_id: u32) -> io::Result { let mut info = drm_mode_fb_cmd { fb_id, ..Default::default() @@ -105,7 +107,7 @@ pub fn add_fb( bpp: u32, depth: u32, handle: u32, -) -> Result { +) -> io::Result { let mut fb = drm_mode_fb_cmd { width, height, @@ -124,7 +126,7 @@ pub fn add_fb( } /// Get info about a framebuffer (with modifiers). -pub fn get_framebuffer2(fd: BorrowedFd<'_>, fb_id: u32) -> Result { +pub fn get_framebuffer2(fd: BorrowedFd<'_>, fb_id: u32) -> io::Result { let mut info = drm_mode_fb_cmd2 { fb_id, ..Default::default() @@ -148,7 +150,7 @@ pub fn add_fb2( offsets: &[u32; 4], modifier: &[u64; 4], flags: u32, -) -> Result { +) -> io::Result { let mut fb = drm_mode_fb_cmd2 { width, height, @@ -169,7 +171,7 @@ pub fn add_fb2( } /// Remove a framebuffer. -pub fn rm_fb(fd: BorrowedFd<'_>, mut id: u32) -> Result<(), Error> { +pub fn rm_fb(fd: BorrowedFd<'_>, mut id: u32) -> io::Result<()> { unsafe { ioctl::mode::rm_fb(fd.as_raw_fd(), &mut id)?; } @@ -182,7 +184,7 @@ pub fn dirty_fb( fd: BorrowedFd<'_>, fb_id: u32, clips: &[drm_clip_rect], -) -> Result { +) -> io::Result { let mut dirty = drm_mode_fb_dirty_cmd { fb_id, num_clips: clips.len() as _, @@ -198,7 +200,7 @@ pub fn dirty_fb( } /// Get info about a CRTC -pub fn get_crtc(fd: BorrowedFd<'_>, crtc_id: u32) -> Result { +pub fn get_crtc(fd: BorrowedFd<'_>, crtc_id: u32) -> io::Result { let mut info = drm_mode_crtc { crtc_id, ..Default::default() @@ -220,7 +222,7 @@ pub fn set_crtc( y: u32, conns: &[u32], mode: Option, -) -> Result { +) -> io::Result { let mut crtc = drm_mode_crtc { set_connectors_ptr: conns.as_ptr() as _, count_connectors: conns.len() as _, @@ -251,7 +253,7 @@ pub fn get_gamma( red: &mut [u16], green: &mut [u16], blue: &mut [u16], -) -> Result { +) -> io::Result { let mut lut = drm_mode_crtc_lut { crtc_id, gamma_size: size as _, @@ -275,7 +277,7 @@ pub fn set_gamma( red: &[u16], green: &[u16], blue: &[u16], -) -> Result { +) -> io::Result { let mut lut = drm_mode_crtc_lut { crtc_id, gamma_size: size as _, @@ -302,7 +304,7 @@ pub fn set_cursor( buf_id: u32, width: u32, height: u32, -) -> Result { +) -> io::Result { let mut cursor = drm_mode_cursor { flags: DRM_MODE_CURSOR_BO, crtc_id, @@ -335,7 +337,7 @@ pub fn set_cursor2( height: u32, hot_x: i32, hot_y: i32, -) -> Result { +) -> io::Result { let mut cursor = drm_mode_cursor2 { flags: DRM_MODE_CURSOR_BO, crtc_id, @@ -361,7 +363,7 @@ pub fn move_cursor( crtc_id: u32, x: i32, y: i32, -) -> Result { +) -> io::Result { let mut cursor = drm_mode_cursor { flags: DRM_MODE_CURSOR_MOVE, crtc_id, @@ -386,7 +388,7 @@ pub fn get_connector( mut modes: Option<&mut Vec>, mut encoders: Option<&mut Vec>, force_probe: bool, -) -> Result { +) -> io::Result { assert_eq!(props.is_some(), prop_values.is_some()); let tmp_mode = drm_mode_modeinfo::default(); @@ -464,7 +466,7 @@ pub fn get_connector( } /// Get info about an encoder -pub fn get_encoder(fd: BorrowedFd<'_>, encoder_id: u32) -> Result { +pub fn get_encoder(fd: BorrowedFd<'_>, encoder_id: u32) -> io::Result { let mut info = drm_mode_get_encoder { encoder_id, ..Default::default() @@ -482,7 +484,7 @@ pub fn get_plane( fd: BorrowedFd<'_>, plane_id: u32, mut formats: Option<&mut Vec>, -) -> Result { +) -> io::Result { let mut sizes = drm_mode_get_plane { plane_id, ..Default::default() @@ -529,7 +531,7 @@ pub fn set_plane( src_y: u32, src_w: u32, src_h: u32, -) -> Result { +) -> io::Result { let mut plane = drm_mode_set_plane { plane_id, crtc_id, @@ -558,7 +560,7 @@ pub fn get_property( prop_id: u32, mut values: Option<&mut Vec>, mut enums: Option<&mut Vec>, -) -> Result { +) -> io::Result { let mut prop = drm_mode_get_property { prop_id, ..Default::default() @@ -595,7 +597,7 @@ pub fn set_connector_property( connector_id: u32, prop_id: u32, value: u64, -) -> Result { +) -> io::Result { let mut prop = drm_mode_connector_set_property { value, prop_id, @@ -614,7 +616,7 @@ pub fn get_property_blob( fd: BorrowedFd<'_>, blob_id: u32, mut data: Option<&mut Vec>, -) -> Result { +) -> io::Result { let mut sizes = drm_mode_get_blob { blob_id, ..Default::default() @@ -649,7 +651,7 @@ pub fn get_property_blob( pub fn create_property_blob( fd: BorrowedFd<'_>, data: &mut [u8], -) -> Result { +) -> io::Result { let mut blob = drm_mode_create_blob { data: data.as_mut_ptr() as _, length: data.len() as _, @@ -664,7 +666,7 @@ pub fn create_property_blob( } /// Destroy a property blob -pub fn destroy_property_blob(fd: BorrowedFd<'_>, id: u32) -> Result { +pub fn destroy_property_blob(fd: BorrowedFd<'_>, id: u32) -> io::Result { let mut blob = drm_mode_destroy_blob { blob_id: id }; unsafe { @@ -681,7 +683,7 @@ pub fn get_properties( obj_type: u32, mut props: Option<&mut Vec>, mut values: Option<&mut Vec>, -) -> Result { +) -> io::Result { assert_eq!(props.is_some(), values.is_some()); let mut sizes = drm_mode_obj_get_properties { @@ -722,7 +724,7 @@ pub fn set_property( obj_id: u32, obj_type: u32, value: u64, -) -> Result<(), Error> { +) -> io::Result<()> { let mut prop = drm_mode_obj_set_property { value, prop_id, @@ -744,7 +746,7 @@ pub fn page_flip( fb_id: u32, flags: u32, sequence: u32, -) -> Result<(), Error> { +) -> io::Result<()> { let mut flip = drm_mode_crtc_page_flip { crtc_id, fb_id, @@ -769,7 +771,7 @@ pub fn atomic_commit( prop_counts: &mut [u32], props: &mut [u32], values: &mut [u64], -) -> Result<(), Error> { +) -> io::Result<()> { let mut atomic = drm_mode_atomic { flags, count_objs: objs.len() as _, @@ -792,7 +794,7 @@ pub fn create_lease( fd: BorrowedFd<'_>, objects: &[u32], flags: u32, -) -> Result { +) -> io::Result { let mut data = drm_mode_create_lease { object_ids: objects.as_ptr() as _, object_count: objects.len() as u32, @@ -811,7 +813,7 @@ pub fn create_lease( pub fn list_lessees( fd: BorrowedFd<'_>, mut lessees: Option<&mut Vec>, -) -> Result { +) -> io::Result { let mut sizes = drm_mode_list_lessees::default(); unsafe { @@ -839,7 +841,7 @@ pub fn list_lessees( pub fn get_lease( fd: BorrowedFd<'_>, mut objects: Option<&mut Vec>, -) -> Result { +) -> io::Result { let mut sizes = drm_mode_get_lease::default(); unsafe { @@ -864,7 +866,7 @@ pub fn get_lease( } /// Revoke previously issued lease -pub fn revoke_lease(fd: BorrowedFd<'_>, lessee_id: u32) -> Result<(), Error> { +pub fn revoke_lease(fd: BorrowedFd<'_>, lessee_id: u32) -> io::Result<()> { let mut data = drm_mode_revoke_lease { lessee_id }; unsafe { @@ -881,8 +883,10 @@ pub mod dumbbuffer { use crate::ioctl; use drm_sys::*; - use crate::result::SystemError as Error; - use std::os::unix::io::{AsRawFd, BorrowedFd}; + use std::{ + io, + os::unix::io::{AsRawFd, BorrowedFd}, + }; /// Create a dumb buffer pub fn create( @@ -891,7 +895,7 @@ pub mod dumbbuffer { height: u32, bpp: u32, flags: u32, - ) -> Result { + ) -> io::Result { let mut db = drm_mode_create_dumb { height, width, @@ -908,7 +912,7 @@ pub mod dumbbuffer { } /// Destroy a dumb buffer - pub fn destroy(fd: BorrowedFd<'_>, handle: u32) -> Result { + pub fn destroy(fd: BorrowedFd<'_>, handle: u32) -> io::Result { let mut db = drm_mode_destroy_dumb { handle }; unsafe { @@ -924,7 +928,7 @@ pub mod dumbbuffer { handle: u32, pad: u32, offset: u64, - ) -> Result { + ) -> io::Result { let mut map = drm_mode_map_dumb { handle, pad, diff --git a/drm-ffi/src/result.rs b/drm-ffi/src/result.rs deleted file mode 100644 index 3222ba7..0000000 --- a/drm-ffi/src/result.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! -//! Error types -//! - -use nix::errno::Errno; -use std::error::Error; -use std::fmt; - -/// A general system error that can be returned by any DRM command. -/// -/// Receiving this error likely indicates a bug in either the program, this -/// crate, or the underlying operating system. -#[derive(Debug)] -pub enum SystemError { - /// A command was attempted using an invalid file descriptor. - InvalidFileDescriptor, - - /// Provided memory area is inaccessible. - /// - /// Receiving this error indicates a bug in this crate. - MemoryFault, - - /// One or more arguments used are invalid. - /// - /// This can be due to the system not supporting a feature or value. - InvalidArgument, - - /// A command was attempted using a non-DRM device. - InvalidFileType, - - /// Permission denied. - PermissionDenied, - - /// An unknown fourcc code was received. - /// - /// This likely indicates that the drm-fourcc crate needs updating. - UnknownFourcc, - - /// Unknown system error. - Unknown { - /// Unknown [`nix::errno::Errno`] returned by the system call. - errno: Errno, - }, -} - -impl fmt::Display for SystemError { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> fmt::Result { - fmt.write_str(match self { - SystemError::InvalidFileDescriptor => "invalid file descriptor", - SystemError::MemoryFault => "invalid memory access", - SystemError::InvalidArgument => "invalid argument", - SystemError::InvalidFileType => "invalid file type", - SystemError::PermissionDenied => "permission denied", - SystemError::UnknownFourcc => "unknown fourcc", - SystemError::Unknown { errno } => { - return write!(fmt, "unknown system error: {}", errno) - } - }) - } -} - -impl Error for SystemError {} - -impl From for SystemError { - fn from(errno: Errno) -> SystemError { - match errno { - Errno::EBADF => SystemError::InvalidFileDescriptor, - Errno::EFAULT => SystemError::MemoryFault, - Errno::EINVAL => SystemError::InvalidArgument, - Errno::ENOTTY => SystemError::InvalidFileDescriptor, - Errno::EACCES => SystemError::PermissionDenied, - _ => SystemError::Unknown { errno }, - } - } -} diff --git a/drm-ffi/src/syncobj.rs b/drm-ffi/src/syncobj.rs index 19f1170..8dd9b5d 100644 --- a/drm-ffi/src/syncobj.rs +++ b/drm-ffi/src/syncobj.rs @@ -5,11 +5,13 @@ use crate::ioctl; use drm_sys::*; -use crate::result::SystemError as Error; -use std::os::unix::io::{AsRawFd, BorrowedFd}; +use std::{ + io, + os::unix::io::{AsRawFd, BorrowedFd}, +}; /// Creates a syncobj. -pub fn create(fd: BorrowedFd<'_>, signaled: bool) -> Result { +pub fn create(fd: BorrowedFd<'_>, signaled: bool) -> io::Result { let mut args = drm_syncobj_create { handle: 0, flags: if signaled { @@ -27,7 +29,7 @@ pub fn create(fd: BorrowedFd<'_>, signaled: bool) -> Result, handle: u32) -> Result { +pub fn destroy(fd: BorrowedFd<'_>, handle: u32) -> io::Result { let mut args = drm_syncobj_destroy { handle, pad: 0 }; unsafe { @@ -42,7 +44,7 @@ pub fn handle_to_fd( fd: BorrowedFd<'_>, handle: u32, export_sync_file: bool, -) -> Result { +) -> io::Result { let mut args = drm_syncobj_handle { handle, flags: if export_sync_file { @@ -66,7 +68,7 @@ pub fn fd_to_handle( fd: BorrowedFd<'_>, syncobj_fd: BorrowedFd<'_>, import_sync_file: bool, -) -> Result { +) -> io::Result { let mut args = drm_syncobj_handle { handle: 0, flags: if import_sync_file { @@ -92,7 +94,7 @@ pub fn wait( timeout_nsec: i64, wait_all: bool, wait_for_submit: bool, -) -> Result { +) -> io::Result { let mut args = drm_syncobj_wait { handles: handles.as_ptr() as _, timeout_nsec, @@ -118,7 +120,7 @@ pub fn wait( } /// Resets (un-signals) one or more syncobjs. -pub fn reset(fd: BorrowedFd<'_>, handles: &[u32]) -> Result { +pub fn reset(fd: BorrowedFd<'_>, handles: &[u32]) -> io::Result { let mut args = drm_syncobj_array { handles: handles.as_ptr() as _, count_handles: handles.len() as _, @@ -133,7 +135,7 @@ pub fn reset(fd: BorrowedFd<'_>, handles: &[u32]) -> Result, handles: &[u32]) -> Result { +pub fn signal(fd: BorrowedFd<'_>, handles: &[u32]) -> io::Result { let mut args = drm_syncobj_array { handles: handles.as_ptr() as _, count_handles: handles.len() as _, @@ -156,7 +158,7 @@ pub fn timeline_wait( wait_all: bool, wait_for_submit: bool, wait_available: bool, -) -> Result { +) -> io::Result { debug_assert_eq!(handles.len(), points.len()); let mut args = drm_syncobj_timeline_wait { @@ -194,7 +196,7 @@ pub fn query( handles: &[u32], points: &mut [u64], last_submitted: bool, -) -> Result { +) -> io::Result { debug_assert_eq!(handles.len(), points.len()); let mut args = drm_syncobj_timeline_array { @@ -222,7 +224,7 @@ pub fn transfer( dst_handle: u32, src_point: u64, dst_point: u64, -) -> Result { +) -> io::Result { let mut args = drm_syncobj_transfer { src_handle, dst_handle, @@ -244,7 +246,7 @@ pub fn timeline_signal( fd: BorrowedFd<'_>, handles: &[u32], points: &[u64], -) -> Result { +) -> io::Result { debug_assert_eq!(handles.len(), points.len()); let mut args = drm_syncobj_timeline_array { diff --git a/examples/syncobj.rs b/examples/syncobj.rs index bd7fc5b..0528248 100644 --- a/examples/syncobj.rs +++ b/examples/syncobj.rs @@ -3,12 +3,13 @@ pub mod utils; use crate::utils::*; use nix::poll::PollFlags; -use std::os::unix::io::{AsFd, OwnedFd}; - -use drm::SystemError; +use std::{ + io, + os::unix::io::{AsFd, OwnedFd}, +}; impl Card { - fn simulate_command_submission(&self) -> Result { + fn simulate_command_submission(&self) -> io::Result { // Create a temporary syncobj to receive the command fence. let syncobj = self.create_syncobj(false)?; diff --git a/src/control/mod.rs b/src/control/mod.rs index 19d13c2..8b67b2d 100644 --- a/src/control/mod.rs +++ b/src/control/mod.rs @@ -29,10 +29,10 @@ //! must be implemented on top of the basic [`super::Device`] trait. use drm_ffi as ffi; -use drm_ffi::result::SystemError; use drm_fourcc::{DrmFourcc, DrmModifier, UnrecognizedFourcc}; use bytemuck::allocation::TransparentWrapperAlloc; +use nix::libc::EINVAL; pub mod atomic; pub mod connector; @@ -52,6 +52,9 @@ use super::util::*; use std::collections::HashMap; use std::convert::TryFrom; +use std::error; +use std::fmt; +use std::io; use std::iter::Zip; use std::mem; use std::num::NonZeroUsize; @@ -84,6 +87,45 @@ pub fn from_u32>(raw: u32) -> Option { RawResourceHandle::new(raw).map(T::from) } +/// Error from [`Device::get_planar_framebuffer`] +#[derive(Debug)] +pub enum GetPlanarFramebufferError { + /// IO error + Io(io::Error), + /// Unrecognized fourcc format + UnrecognizedFourcc(drm_fourcc::UnrecognizedFourcc), +} + +impl fmt::Display for GetPlanarFramebufferError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Io(err) => write!(f, "{}", err), + Self::UnrecognizedFourcc(err) => write!(f, "{}", err), + } + } +} + +impl error::Error for GetPlanarFramebufferError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + Self::Io(err) => Some(err), + Self::UnrecognizedFourcc(err) => Some(err), + } + } +} + +impl From for GetPlanarFramebufferError { + fn from(err: io::Error) -> Self { + Self::Io(err) + } +} + +impl From for GetPlanarFramebufferError { + fn from(err: UnrecognizedFourcc) -> Self { + Self::UnrecognizedFourcc(err) + } +} + /// This trait should be implemented by any object that acts as a DRM device and /// provides modesetting functionality. /// @@ -99,7 +141,7 @@ pub fn from_u32>(raw: u32) -> Option { /// ``` pub trait Device: super::Device { /// Gets the set of resource handles that this device currently controls - fn resource_handles(&self) -> Result { + fn resource_handles(&self) -> io::Result { let mut fbs = Vec::new(); let mut crtcs = Vec::new(); let mut connectors = Vec::new(); @@ -128,7 +170,7 @@ pub trait Device: super::Device { } /// Gets the set of plane handles that this device currently has - fn plane_handles(&self) -> Result, SystemError> { + fn plane_handles(&self) -> io::Result> { let mut planes = Vec::new(); let _ = ffi::mode::get_plane_resources(self.as_fd(), Some(&mut planes))?; Ok(unsafe { transmute_vec_from_u32(planes) }) @@ -149,7 +191,7 @@ pub trait Device: super::Device { &self, handle: connector::Handle, force_probe: bool, - ) -> Result { + ) -> io::Result { // Maximum number of encoders is 3 due to kernel restrictions let mut encoders = Vec::new(); let mut modes = Vec::new(); @@ -183,7 +225,7 @@ pub trait Device: super::Device { } /// Returns information about a specific encoder - fn get_encoder(&self, handle: encoder::Handle) -> Result { + fn get_encoder(&self, handle: encoder::Handle) -> io::Result { let info = ffi::mode::get_encoder(self.as_fd(), handle.into())?; let enc = encoder::Info { @@ -198,7 +240,7 @@ pub trait Device: super::Device { } /// Returns information about a specific CRTC - fn get_crtc(&self, handle: crtc::Handle) -> Result { + fn get_crtc(&self, handle: crtc::Handle) -> io::Result { let info = ffi::mode::get_crtc(self.as_fd(), handle.into())?; let crtc = crtc::Info { @@ -223,7 +265,7 @@ pub trait Device: super::Device { pos: (u32, u32), conns: &[connector::Handle], mode: Option, - ) -> Result<(), SystemError> { + ) -> io::Result<()> { let _info = ffi::mode::set_crtc( self.as_fd(), handle.into(), @@ -238,10 +280,7 @@ pub trait Device: super::Device { } /// Returns information about a specific framebuffer - fn get_framebuffer( - &self, - handle: framebuffer::Handle, - ) -> Result { + fn get_framebuffer(&self, handle: framebuffer::Handle) -> io::Result { let info = ffi::mode::get_framebuffer(self.as_fd(), handle.into())?; let fb = framebuffer::Info { @@ -260,13 +299,10 @@ pub trait Device: super::Device { fn get_planar_framebuffer( &self, handle: framebuffer::Handle, - ) -> Result { + ) -> Result { let info = ffi::mode::get_framebuffer2(self.as_fd(), handle.into())?; - let pixel_format = match DrmFourcc::try_from(info.pixel_format) { - Ok(pixel_format) => pixel_format, - Err(UnrecognizedFourcc(_)) => return Err(SystemError::UnknownFourcc), - }; + let pixel_format = DrmFourcc::try_from(info.pixel_format)?; let flags = FbCmd2Flags::from_bits_truncate(info.flags); let modifier = flags @@ -293,7 +329,7 @@ pub trait Device: super::Device { buffer: &B, depth: u32, bpp: u32, - ) -> Result + ) -> io::Result where B: buffer::Buffer + ?Sized, { @@ -316,7 +352,7 @@ pub trait Device: super::Device { &self, planar_buffer: &B, flags: FbCmd2Flags, - ) -> Result + ) -> io::Result where B: buffer::PlanarBuffer + ?Sized, { @@ -356,11 +392,7 @@ pub trait Device: super::Device { } /// Mark parts of a framebuffer dirty - fn dirty_framebuffer( - &self, - handle: framebuffer::Handle, - clips: &[ClipRect], - ) -> Result<(), SystemError> { + fn dirty_framebuffer(&self, handle: framebuffer::Handle, clips: &[ClipRect]) -> io::Result<()> { ffi::mode::dirty_fb(self.as_fd(), handle.into(), unsafe { // SAFETY: ClipRect is repr(transparent) for drm_clip_rect core::slice::from_raw_parts(clips.as_ptr() as *const ffi::drm_clip_rect, clips.len()) @@ -369,12 +401,12 @@ pub trait Device: super::Device { } /// Destroy a framebuffer - fn destroy_framebuffer(&self, handle: framebuffer::Handle) -> Result<(), SystemError> { + fn destroy_framebuffer(&self, handle: framebuffer::Handle) -> io::Result<()> { ffi::mode::rm_fb(self.as_fd(), handle.into()) } /// Returns information about a specific plane - fn get_plane(&self, handle: plane::Handle) -> Result { + fn get_plane(&self, handle: plane::Handle) -> io::Result { let mut formats = Vec::new(); let info = ffi::mode::get_plane(self.as_fd(), handle.into(), Some(&mut formats))?; @@ -401,7 +433,7 @@ pub trait Device: super::Device { flags: u32, crtc_rect: (i32, i32, u32, u32), src_rect: (u32, u32, u32, u32), - ) -> Result<(), SystemError> { + ) -> io::Result<()> { let _info = ffi::mode::set_plane( self.as_fd(), handle.into(), @@ -422,7 +454,7 @@ pub trait Device: super::Device { } /// Returns information about a specific property. - fn get_property(&self, handle: property::Handle) -> Result { + fn get_property(&self, handle: property::Handle) -> io::Result { let mut values = Vec::new(); let mut enums = Vec::new(); @@ -496,14 +528,14 @@ pub trait Device: super::Device { handle: T, prop: property::Handle, value: property::RawValue, - ) -> Result<(), SystemError> { + ) -> io::Result<()> { ffi::mode::set_property(self.as_fd(), prop.into(), handle.into(), T::FFI_TYPE, value)?; Ok(()) } /// Create a property blob value from a given data blob - fn create_property_blob(&self, data: &T) -> Result, SystemError> { + fn create_property_blob(&self, data: &T) -> io::Result> { let data = unsafe { std::slice::from_raw_parts_mut(data as *const _ as *mut u8, mem::size_of::()) }; @@ -513,21 +545,21 @@ pub trait Device: super::Device { } /// Get a property blob's data - fn get_property_blob(&self, blob: u64) -> Result, SystemError> { + fn get_property_blob(&self, blob: u64) -> io::Result> { let mut data = Vec::new(); let _ = ffi::mode::get_property_blob(self.as_fd(), blob as u32, Some(&mut data))?; Ok(data) } /// Destroy a given property blob value - fn destroy_property_blob(&self, blob: u64) -> Result<(), SystemError> { + fn destroy_property_blob(&self, blob: u64) -> io::Result<()> { ffi::mode::destroy_property_blob(self.as_fd(), blob as u32)?; Ok(()) } /// Returns the set of [`Mode`]s that a particular connector supports. - fn get_modes(&self, handle: connector::Handle) -> Result, SystemError> { + fn get_modes(&self, handle: connector::Handle) -> io::Result> { let mut modes = Vec::new(); let _ffi_info = ffi::mode::get_connector( @@ -544,10 +576,7 @@ pub trait Device: super::Device { } /// Gets a list of property handles and values for this resource. - fn get_properties( - &self, - handle: T, - ) -> Result { + fn get_properties(&self, handle: T) -> io::Result { let mut prop_ids = Vec::new(); let mut prop_vals = Vec::new(); @@ -574,13 +603,13 @@ pub trait Device: super::Device { red: &mut [u16], green: &mut [u16], blue: &mut [u16], - ) -> Result<(), SystemError> { + ) -> io::Result<()> { let crtc_info = self.get_crtc(crtc)?; if crtc_info.gamma_length as usize > red.len() || crtc_info.gamma_length as usize > green.len() || crtc_info.gamma_length as usize > blue.len() { - return Err(SystemError::InvalidArgument); + return Err(io::Error::from_raw_os_error(EINVAL)); } ffi::mode::get_gamma( @@ -602,13 +631,13 @@ pub trait Device: super::Device { red: &[u16], green: &[u16], blue: &[u16], - ) -> Result<(), SystemError> { + ) -> io::Result<()> { let crtc_info = self.get_crtc(crtc)?; if crtc_info.gamma_length as usize > red.len() || crtc_info.gamma_length as usize > green.len() || crtc_info.gamma_length as usize > blue.len() { - return Err(SystemError::InvalidArgument); + return Err(io::Error::from_raw_os_error(EINVAL)); } ffi::mode::set_gamma( @@ -624,13 +653,13 @@ pub trait Device: super::Device { } /// Open a GEM buffer handle by name - fn open_buffer(&self, name: buffer::Name) -> Result { + fn open_buffer(&self, name: buffer::Name) -> io::Result { let info = drm_ffi::gem::open(self.as_fd(), name.into())?; Ok(from_u32(info.handle).unwrap()) } /// Close a GEM buffer handle - fn close_buffer(&self, handle: buffer::Handle) -> Result<(), SystemError> { + fn close_buffer(&self, handle: buffer::Handle) -> io::Result<()> { let _info = drm_ffi::gem::close(self.as_fd(), handle.into())?; Ok(()) } @@ -641,7 +670,7 @@ pub trait Device: super::Device { size: (u32, u32), format: buffer::DrmFourcc, bpp: u32, - ) -> Result { + ) -> io::Result { let info = drm_ffi::mode::dumbbuffer::create(self.as_fd(), size.0, size.1, bpp, 0)?; let dumb = DumbBuffer { @@ -655,17 +684,15 @@ pub trait Device: super::Device { Ok(dumb) } /// Map the buffer for access - fn map_dumb_buffer<'a>( - &self, - buffer: &'a mut DumbBuffer, - ) -> Result, SystemError> { + fn map_dumb_buffer<'a>(&self, buffer: &'a mut DumbBuffer) -> io::Result> { let info = drm_ffi::mode::dumbbuffer::map(self.as_fd(), buffer.handle.into(), 0, 0)?; let map = { use nix::sys::mman; let prot = mman::ProtFlags::PROT_READ | mman::ProtFlags::PROT_WRITE; let flags = mman::MapFlags::MAP_SHARED; - let length = NonZeroUsize::new(buffer.length).ok_or(SystemError::InvalidArgument)?; + let length = NonZeroUsize::new(buffer.length) + .ok_or_else(|| io::Error::from_raw_os_error(EINVAL))?; let fd = self.as_fd(); let offset = info.offset as _; unsafe { mman::mmap(None, length, prot, flags, Some(fd), offset)? } @@ -680,7 +707,7 @@ pub trait Device: super::Device { } /// Free the memory resources of a dumb buffer - fn destroy_dumb_buffer(&self, buffer: DumbBuffer) -> Result<(), SystemError> { + fn destroy_dumb_buffer(&self, buffer: DumbBuffer) -> io::Result<()> { let _info = drm_ffi::mode::dumbbuffer::destroy(self.as_fd(), buffer.handle.into())?; Ok(()) @@ -691,7 +718,7 @@ pub trait Device: super::Device { /// A buffer argument of [`None`] will clear the cursor. #[deprecated(note = "Usage of deprecated ioctl set_cursor: use a cursor plane instead")] #[allow(deprecated)] - fn set_cursor(&self, crtc: crtc::Handle, buffer: Option<&B>) -> Result<(), SystemError> + fn set_cursor(&self, crtc: crtc::Handle, buffer: Option<&B>) -> io::Result<()> where B: buffer::Buffer + ?Sized, { @@ -717,7 +744,7 @@ pub trait Device: super::Device { crtc: crtc::Handle, buffer: Option<&B>, hotspot: (i32, i32), - ) -> Result<(), SystemError> + ) -> io::Result<()> where B: buffer::Buffer + ?Sized, { @@ -735,7 +762,7 @@ pub trait Device: super::Device { /// Moves a set cursor on a given crtc #[deprecated(note = "Usage of deprecated ioctl move_cursor: use a cursor plane instead")] #[allow(deprecated)] - fn move_cursor(&self, crtc: crtc::Handle, pos: (i32, i32)) -> Result<(), SystemError> { + fn move_cursor(&self, crtc: crtc::Handle, pos: (i32, i32)) -> io::Result<()> { drm_ffi::mode::move_cursor(self.as_fd(), crtc.into(), pos.0, pos.1)?; Ok(()) @@ -746,7 +773,7 @@ pub trait Device: super::Device { &self, flags: AtomicCommitFlags, mut req: atomic::AtomicModeReq, - ) -> Result<(), SystemError> { + ) -> io::Result<()> { drm_ffi::mode::atomic_commit( self.as_fd(), flags.bits(), @@ -758,17 +785,13 @@ pub trait Device: super::Device { } /// Convert a prime file descriptor to a GEM buffer handle - fn prime_fd_to_buffer(&self, fd: BorrowedFd<'_>) -> Result { + fn prime_fd_to_buffer(&self, fd: BorrowedFd<'_>) -> io::Result { let info = ffi::gem::fd_to_handle(self.as_fd(), fd)?; Ok(from_u32(info.handle).unwrap()) } /// Convert a GEM buffer handle to a prime file descriptor - fn buffer_to_prime_fd( - &self, - handle: buffer::Handle, - flags: u32, - ) -> Result { + fn buffer_to_prime_fd(&self, handle: buffer::Handle, flags: u32) -> io::Result { let info = ffi::gem::handle_to_fd(self.as_fd(), handle.into(), flags)?; Ok(unsafe { OwnedFd::from_raw_fd(info.fd) }) } @@ -780,7 +803,7 @@ pub trait Device: super::Device { framebuffer: framebuffer::Handle, flags: PageFlipFlags, target_sequence: Option, - ) -> Result<(), SystemError> { + ) -> io::Result<()> { let mut flags = flags.bits(); let sequence = match target_sequence { @@ -807,13 +830,13 @@ pub trait Device: super::Device { } /// Creates a syncobj. - fn create_syncobj(&self, signalled: bool) -> Result { + fn create_syncobj(&self, signalled: bool) -> io::Result { let info = ffi::syncobj::create(self.as_fd(), signalled)?; Ok(from_u32(info.handle).unwrap()) } /// Destroys a syncobj. - fn destroy_syncobj(&self, handle: syncobj::Handle) -> Result<(), SystemError> { + fn destroy_syncobj(&self, handle: syncobj::Handle) -> io::Result<()> { ffi::syncobj::destroy(self.as_fd(), handle.into())?; Ok(()) } @@ -823,7 +846,7 @@ pub trait Device: super::Device { &self, handle: syncobj::Handle, export_sync_file: bool, - ) -> Result { + ) -> io::Result { let info = ffi::syncobj::handle_to_fd(self.as_fd(), handle.into(), export_sync_file)?; Ok(unsafe { OwnedFd::from_raw_fd(info.fd) }) } @@ -833,7 +856,7 @@ pub trait Device: super::Device { &self, fd: BorrowedFd<'_>, import_sync_file: bool, - ) -> Result { + ) -> io::Result { let info = ffi::syncobj::fd_to_handle(self.as_fd(), fd, import_sync_file)?; Ok(from_u32(info.handle).unwrap()) } @@ -845,7 +868,7 @@ pub trait Device: super::Device { timeout_nsec: i64, wait_all: bool, wait_for_submit: bool, - ) -> Result { + ) -> io::Result { let info = ffi::syncobj::wait( self.as_fd(), bytemuck::cast_slice(handles), @@ -857,13 +880,13 @@ pub trait Device: super::Device { } /// Resets (un-signals) one or more syncobjs. - fn syncobj_reset(&self, handles: &[syncobj::Handle]) -> Result<(), SystemError> { + fn syncobj_reset(&self, handles: &[syncobj::Handle]) -> io::Result<()> { ffi::syncobj::reset(self.as_fd(), bytemuck::cast_slice(handles))?; Ok(()) } /// Signals one or more syncobjs. - fn syncobj_signal(&self, handles: &[syncobj::Handle]) -> Result<(), SystemError> { + fn syncobj_signal(&self, handles: &[syncobj::Handle]) -> io::Result<()> { ffi::syncobj::signal(self.as_fd(), bytemuck::cast_slice(handles))?; Ok(()) } @@ -877,7 +900,7 @@ pub trait Device: super::Device { wait_all: bool, wait_for_submit: bool, wait_available: bool, - ) -> Result { + ) -> io::Result { let info = ffi::syncobj::timeline_wait( self.as_fd(), bytemuck::cast_slice(handles), @@ -896,7 +919,7 @@ pub trait Device: super::Device { handles: &[syncobj::Handle], points: &mut [u64], last_submitted: bool, - ) -> Result<(), SystemError> { + ) -> io::Result<()> { ffi::syncobj::query( self.as_fd(), bytemuck::cast_slice(handles), @@ -913,7 +936,7 @@ pub trait Device: super::Device { dst_handle: syncobj::Handle, src_point: u64, dst_point: u64, - ) -> Result<(), SystemError> { + ) -> io::Result<()> { ffi::syncobj::transfer( self.as_fd(), src_handle.into(), @@ -929,7 +952,7 @@ pub trait Device: super::Device { &self, handles: &[syncobj::Handle], points: &[u64], - ) -> Result<(), SystemError> { + ) -> io::Result<()> { ffi::syncobj::timeline_signal(self.as_fd(), bytemuck::cast_slice(handles), points)?; Ok(()) } @@ -939,7 +962,7 @@ pub trait Device: super::Device { &self, objects: &[RawResourceHandle], flags: OFlag, - ) -> Result<(LeaseId, OwnedFd), SystemError> { + ) -> io::Result<(LeaseId, OwnedFd)> { let lease = ffi::mode::create_lease( self.as_fd(), bytemuck::cast_slice(objects), @@ -952,19 +975,19 @@ pub trait Device: super::Device { } /// List active lessees - fn list_lessees(&self) -> Result, SystemError> { + fn list_lessees(&self) -> io::Result> { let mut lessees = Vec::new(); ffi::mode::list_lessees(self.as_fd(), Some(&mut lessees))?; Ok(unsafe { transmute_vec_from_u32(lessees) }) } /// Revoke a previously issued drm lease - fn revoke_lease(&self, lessee_id: LeaseId) -> Result<(), SystemError> { + fn revoke_lease(&self, lessee_id: LeaseId) -> io::Result<()> { ffi::mode::revoke_lease(self.as_fd(), lessee_id.get()) } /// Receive pending events - fn receive_events(&self) -> Result + fn receive_events(&self) -> io::Result where Self: Sized, { @@ -986,7 +1009,7 @@ pub struct LeaseResources { } /// Query lease resources -pub fn get_lease(lease: D) -> Result { +pub fn get_lease(lease: D) -> io::Result { let mut crtcs = Vec::new(); let mut connectors = Vec::new(); let mut planes = Vec::new(); @@ -1292,8 +1315,8 @@ impl From for ffi::drm_mode_modeinfo { } } -impl std::fmt::Debug for Mode { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl fmt::Debug for Mode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Mode") .field("name", &self.name()) .field("clock", &self.clock()) @@ -1409,10 +1432,7 @@ pub struct PropertyValueSet { impl PropertyValueSet { /// Returns a HashMap mapping property names to info - pub fn as_hashmap( - &self, - device: &impl Device, - ) -> Result, SystemError> { + pub fn as_hashmap(&self, device: &impl Device) -> io::Result> { let mut map = HashMap::new(); for id in self.prop_ids.iter() { let info = device.get_property(*id)?; diff --git a/src/lib.rs b/src/lib.rs index 74a30f5..de08b66 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,11 +34,15 @@ pub mod buffer; pub mod control; use std::ffi::{OsStr, OsString}; -use std::os::unix::{ffi::OsStringExt, io::AsFd}; use std::time::Duration; +use std::{ + io, + os::unix::{ffi::OsStringExt, io::AsFd}, +}; + +use nix::libc::EINVAL; use crate::util::*; -pub use drm_ffi::result::SystemError; /// This trait should be implemented by any object that acts as a DRM device. It /// is a prerequisite for using any DRM functionality. @@ -98,43 +102,39 @@ pub trait Device: AsFd { /// /// This function is only available to processes with CAP_SYS_ADMIN /// privileges (usually as root) - fn acquire_master_lock(&self) -> Result<(), SystemError> { + fn acquire_master_lock(&self) -> io::Result<()> { drm_ffi::auth::acquire_master(self.as_fd())?; Ok(()) } /// Releases the DRM Master lock for another process to use. - fn release_master_lock(&self) -> Result<(), SystemError> { + fn release_master_lock(&self) -> io::Result<()> { drm_ffi::auth::release_master(self.as_fd())?; Ok(()) } /// Generates an [`AuthToken`] for this process. #[deprecated(note = "Consider opening a render node instead.")] - fn generate_auth_token(&self) -> Result { + fn generate_auth_token(&self) -> io::Result { let token = drm_ffi::auth::get_magic_token(self.as_fd())?; Ok(AuthToken(token.magic)) } /// Authenticates an [`AuthToken`] from another process. - fn authenticate_auth_token(&self, token: AuthToken) -> Result<(), SystemError> { + fn authenticate_auth_token(&self, token: AuthToken) -> io::Result<()> { drm_ffi::auth::auth_magic_token(self.as_fd(), token.0)?; Ok(()) } /// Requests the driver to expose or hide certain capabilities. See /// [`ClientCapability`] for more information. - fn set_client_capability( - &self, - cap: ClientCapability, - enable: bool, - ) -> Result<(), SystemError> { + fn set_client_capability(&self, cap: ClientCapability, enable: bool) -> io::Result<()> { drm_ffi::set_capability(self.as_fd(), cap as u64, enable)?; Ok(()) } /// Gets the bus ID of this device. - fn get_bus_id(&self) -> Result { + fn get_bus_id(&self) -> io::Result { let mut buffer = Vec::new(); let _ = drm_ffi::get_bus_id(self.as_fd(), Some(&mut buffer))?; let bus_id = OsString::from_vec(buffer); @@ -144,21 +144,21 @@ pub trait Device: AsFd { /// Check to see if our [`AuthToken`] has been authenticated /// by the DRM Master - fn authenticated(&self) -> Result { + fn authenticated(&self) -> io::Result { let client = drm_ffi::get_client(self.as_fd(), 0)?; Ok(client.auth == 1) } /// Gets the value of a capability. - fn get_driver_capability(&self, cap: DriverCapability) -> Result { + fn get_driver_capability(&self, cap: DriverCapability) -> io::Result { let cap = drm_ffi::get_capability(self.as_fd(), cap as u64)?; Ok(cap.value) } /// # Possible errors: - /// - [`SystemError::MemoryFault`]: Kernel could not copy fields into userspace + /// - `EFAULT`: Kernel could not copy fields into userspace #[allow(missing_docs)] - fn get_driver(&self) -> Result { + fn get_driver(&self) -> io::Result { let mut name = Vec::new(); let mut date = Vec::new(); let mut desc = Vec::new(); @@ -186,13 +186,13 @@ pub trait Device: AsFd { flags: VblankWaitFlags, high_crtc: u32, user_data: usize, - ) -> Result { + ) -> io::Result { use drm_ffi::drm_vblank_seq_type::_DRM_VBLANK_HIGH_CRTC_MASK; use drm_ffi::_DRM_VBLANK_HIGH_CRTC_SHIFT; let high_crtc_mask = _DRM_VBLANK_HIGH_CRTC_MASK >> _DRM_VBLANK_HIGH_CRTC_SHIFT; if (high_crtc & !high_crtc_mask) != 0 { - return Err(SystemError::InvalidArgument); + return Err(io::Error::from_raw_os_error(EINVAL)); } let (sequence, wait_type) = match target_sequence {