Skip to content

Commit

Permalink
WIP Use Rustix
Browse files Browse the repository at this point in the history
Updates `drm-ffi` to use Rustix.

Not *too* hard to update by defining macros like Nix had, though it's
probably not ideal.

The generic ioctl API for Rustix seems a bit awkward when dealing with
APIs like drm that involve very large numbers of ioctls. Instead of
generating functions with a macro like this, it's possible to define
types aliases with `ReadWriteOpcode`, etc. But it's still necessary to
deal with `Getter`/`Setter`, etc...
  • Loading branch information
ids1024 committed Nov 7, 2023
1 parent 34fcd78 commit bed1c7f
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 88 deletions.
6 changes: 1 addition & 5 deletions drm-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ edition = "2021"

[dependencies]
drm-sys = { path = "drm-sys", version = "0.5.0" }

[dependencies.nix]
version = "0.27"
default-features = false
features = ["ioctl"]
rustix = { version = "0.38.21" }

[features]
use_bindgen = ["drm-sys/use_bindgen"]
10 changes: 5 additions & 5 deletions drm-ffi/src/gem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use drm_sys::*;

use std::{
io,
os::unix::io::{AsRawFd, BorrowedFd},
os::unix::io::{AsFd, AsRawFd, BorrowedFd},
};

/// Open a GEM object given it's 32-bit name, returning the handle.
Expand All @@ -18,7 +18,7 @@ pub fn open(fd: BorrowedFd<'_>, name: u32) -> io::Result<drm_gem_open> {
};

unsafe {
ioctl::gem::open(fd.as_raw_fd(), &mut gem)?;
ioctl::gem::open(fd.as_fd(), &mut gem)?;
}

Ok(gem)
Expand All @@ -32,7 +32,7 @@ pub fn close(fd: BorrowedFd<'_>, handle: u32) -> io::Result<drm_gem_close> {
};

unsafe {
ioctl::gem::close(fd.as_raw_fd(), &gem)?;
ioctl::gem::close(fd.as_fd(), &gem)?;
}

Ok(gem)
Expand All @@ -47,7 +47,7 @@ pub fn handle_to_fd(fd: BorrowedFd<'_>, handle: u32, flags: u32) -> io::Result<d
};

unsafe {
ioctl::gem::prime_handle_to_fd(fd.as_raw_fd(), &mut prime)?;
ioctl::gem::prime_handle_to_fd(fd.as_fd(), &mut prime)?;
}

Ok(prime)
Expand All @@ -61,7 +61,7 @@ pub fn fd_to_handle(fd: BorrowedFd<'_>, primefd: BorrowedFd<'_>) -> io::Result<d
};

unsafe {
ioctl::gem::prime_fd_to_handle(fd.as_raw_fd(), &mut prime)?;
ioctl::gem::prime_fd_to_handle(fd.as_fd(), &mut prime)?;
}

Ok(prime)
Expand Down
67 changes: 66 additions & 1 deletion drm-ffi/src/ioctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,71 @@

use drm_sys::*;

use rustix::ioctl::{CompileTimeOpcode, Ioctl, IoctlOutput};
use std::{ffi::c_void, marker::PhantomData};

struct GetterSetter<'a, Opcode: CompileTimeOpcode, T>(&'a mut T, PhantomData<Opcode>);

unsafe impl<'a, Opcode: CompileTimeOpcode, T> Ioctl for GetterSetter<'a, Opcode, T> {
type Output = std::ffi::c_int;
const IS_MUTATING: bool = true;
const OPCODE: rustix::ioctl::Opcode = Opcode::OPCODE;

fn as_ptr(&mut self) -> *mut c_void {
self.0 as *mut T as *mut c_void
}

unsafe fn output_from_ptr(
output: IoctlOutput,
_ptr: *mut c_void,
) -> rustix::io::Result<std::ffi::c_int> {
Ok(output)
}
}

macro_rules! ioctl_readwrite {
($name:ident, $ioty:expr, $nr:expr, $ty:ty) => {
pub unsafe fn $name(fd: std::os::fd::BorrowedFd, data: &mut $ty) -> std::io::Result<()> {
type Opcode = rustix::ioctl::ReadWriteOpcode<$ioty, $nr, $ty>;
rustix::ioctl::ioctl(
fd,
crate::ioctl::GetterSetter::<Opcode, $ty>(data, std::marker::PhantomData),
)?;
Ok(())
}
};
}

macro_rules! ioctl_read {
($name:ident, $ioty:expr, $nr:expr, $ty:ty) => {
pub unsafe fn $name(fd: std::os::fd::BorrowedFd, data: &mut $ty) -> std::io::Result<()> {
type Opcode = rustix::ioctl::ReadOpcode<$ioty, $nr, $ty>;
*data = rustix::ioctl::ioctl(fd, rustix::ioctl::Getter::<Opcode, $ty>::new())?;
Ok(())
}
};
}

macro_rules! ioctl_write_ptr {
($name:ident, $ioty:expr, $nr:expr, $ty:ty) => {
pub unsafe fn $name(fd: std::os::fd::BorrowedFd, data: &$ty) -> std::io::Result<()> {
type Opcode = rustix::ioctl::WriteOpcode<$ioty, $nr, $ty>;
rustix::ioctl::ioctl(fd, rustix::ioctl::Setter::<Opcode, $ty>::new(*data))?;
Ok(())
}
};
}

macro_rules! ioctl_none {
($name:ident, $ioty:expr, $nr:expr) => {
pub unsafe fn $name(fd: std::os::fd::BorrowedFd) -> std::io::Result<()> {
type Opcode = rustix::ioctl::NoneOpcode<$ioty, $nr, ()>;
rustix::ioctl::ioctl(fd, rustix::ioctl::NoArg::<Opcode>::new())?;
Ok(())
}
};
}

/// Gets the bus ID of the device
///
/// # Locks DRM mutex: Yes
Expand Down Expand Up @@ -95,7 +160,7 @@ ioctl_readwrite!(wait_vblank, DRM_IOCTL_BASE, 0x3a, drm_wait_vblank);

pub(crate) mod mode {
use drm_sys::*;
use nix::libc::c_uint;
use std::ffi::c_uint;

/// Modesetting resources
ioctl_readwrite!(get_resources, DRM_IOCTL_BASE, 0xA0, drm_mode_card_res);
Expand Down
35 changes: 16 additions & 19 deletions drm-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@

pub use drm_sys::{self, *};

#[macro_use]
extern crate nix;

#[macro_use]
pub(crate) mod utils;

Expand All @@ -18,10 +15,10 @@ mod ioctl;
pub mod mode;
pub mod syncobj;

use nix::libc::{c_int, c_ulong};
use std::{
ffi::{c_int, c_ulong},
io,
os::unix::io::{AsRawFd, BorrowedFd},
os::unix::io::{AsFd, BorrowedFd},
};

///
Expand All @@ -33,15 +30,15 @@ pub mod auth {

use std::{
io,
os::unix::io::{AsRawFd, BorrowedFd},
os::unix::io::{AsFd, BorrowedFd},
};

/// Get the 'Magic Authentication Token' for this file descriptor.
pub fn get_magic_token(fd: BorrowedFd<'_>) -> io::Result<drm_auth> {
let mut auth = drm_auth::default();

unsafe {
ioctl::get_token(fd.as_raw_fd(), &mut auth)?;
ioctl::get_token(fd.as_fd(), &mut auth)?;
}

Ok(auth)
Expand All @@ -52,7 +49,7 @@ pub mod auth {
let token = drm_auth { magic: auth };

unsafe {
ioctl::auth_token(fd.as_raw_fd(), &token)?;
ioctl::auth_token(fd.as_fd(), &token)?;
}

Ok(token)
Expand All @@ -61,7 +58,7 @@ pub mod auth {
/// Acquire the 'Master DRM Lock' for this file descriptor.
pub fn acquire_master(fd: BorrowedFd<'_>) -> io::Result<()> {
unsafe {
ioctl::acquire_master(fd.as_raw_fd())?;
ioctl::acquire_master(fd.as_fd())?;
}

Ok(())
Expand All @@ -70,7 +67,7 @@ pub mod auth {
/// Release the 'Master DRM Lock' for this file descriptor.
pub fn release_master(fd: BorrowedFd<'_>) -> io::Result<()> {
unsafe {
ioctl::release_master(fd.as_raw_fd())?;
ioctl::release_master(fd.as_fd())?;
}

Ok(())
Expand All @@ -81,7 +78,7 @@ pub mod auth {
pub fn get_bus_id(fd: BorrowedFd<'_>, mut buf: Option<&mut Vec<u8>>) -> io::Result<drm_unique> {
let mut sizes = drm_unique::default();
unsafe {
ioctl::get_bus_id(fd.as_raw_fd(), &mut sizes)?;
ioctl::get_bus_id(fd.as_fd(), &mut sizes)?;
}

if buf.is_none() {
Expand All @@ -96,7 +93,7 @@ pub fn get_bus_id(fd: BorrowedFd<'_>, mut buf: Option<&mut Vec<u8>>) -> io::Resu
};

unsafe {
ioctl::get_bus_id(fd.as_raw_fd(), &mut busid)?;
ioctl::get_bus_id(fd.as_fd(), &mut busid)?;
}

map_set!(buf, busid.unique_len as usize);
Expand All @@ -119,7 +116,7 @@ pub fn get_interrupt_from_bus_id(
};

unsafe {
ioctl::get_irq_from_bus_id(fd.as_raw_fd(), &mut irq)?;
ioctl::get_irq_from_bus_id(fd.as_fd(), &mut irq)?;
}

Ok(irq)
Expand All @@ -133,7 +130,7 @@ pub fn get_client(fd: BorrowedFd<'_>, idx: c_int) -> io::Result<drm_client> {
};

unsafe {
ioctl::get_client(fd.as_raw_fd(), &mut client)?;
ioctl::get_client(fd.as_fd(), &mut client)?;
}

Ok(client)
Expand All @@ -147,7 +144,7 @@ pub fn get_capability(fd: BorrowedFd<'_>, cty: u64) -> io::Result<drm_get_cap> {
};

unsafe {
ioctl::get_cap(fd.as_raw_fd(), &mut cap)?;
ioctl::get_cap(fd.as_fd(), &mut cap)?;
}

Ok(cap)
Expand All @@ -161,7 +158,7 @@ pub fn set_capability(fd: BorrowedFd<'_>, cty: u64, val: bool) -> io::Result<drm
};

unsafe {
ioctl::set_cap(fd.as_raw_fd(), &cap)?;
ioctl::set_cap(fd.as_fd(), &cap)?;
}

Ok(cap)
Expand All @@ -176,7 +173,7 @@ pub fn get_version(
) -> io::Result<drm_version> {
let mut sizes = drm_version::default();
unsafe {
ioctl::get_version(fd.as_raw_fd(), &mut sizes)?;
ioctl::get_version(fd.as_fd(), &mut sizes)?;
}

map_reserve!(name_buf, sizes.name_len as usize);
Expand All @@ -194,7 +191,7 @@ pub fn get_version(
};

unsafe {
ioctl::get_version(fd.as_raw_fd(), &mut version)?;
ioctl::get_version(fd.as_fd(), &mut version)?;
}

map_set!(name_buf, version.name_len as usize);
Expand Down Expand Up @@ -223,7 +220,7 @@ pub fn wait_vblank(
};

unsafe {
ioctl::wait_vblank(fd.as_raw_fd(), &mut wait_vblank)?;
ioctl::wait_vblank(fd.as_fd(), &mut wait_vblank)?;
};

Ok(unsafe { wait_vblank.reply })
Expand Down
Loading

0 comments on commit bed1c7f

Please sign in to comment.