use std::{
io,
os::fd::{BorrowedFd, FromRawFd as _, OwnedFd, RawFd},
};
use rustix::{
fs::OFlags,
io::Errno,
ioctl::{Updater, ioctl, opcode},
};
const DMA_HEAP_IOC_MAGIC: u8 = b'H';
const DMA_HEAP_IOC_ALLOC: u8 = 0;
#[derive(Default)]
#[repr(C)]
struct dma_heap_allocation_data {
len: u64,
fd: u32,
fd_flags: u32,
heap_flags: u64,
}
const DMA_HEAP_IOC_ALLOC_OPCODE: u32 =
opcode::read_write::<dma_heap_allocation_data>(DMA_HEAP_IOC_MAGIC, DMA_HEAP_IOC_ALLOC);
fn dma_heap_alloc_ioctl(fd: BorrowedFd<'_>, data: &mut dma_heap_allocation_data) -> io::Result<()> {
let ioctl_type =
unsafe { Updater::<DMA_HEAP_IOC_ALLOC_OPCODE, dma_heap_allocation_data>::new(data) };
unsafe { ioctl(fd, ioctl_type) }.map_err(<Errno as Into<io::Error>>::into)
}
pub(crate) fn dma_heap_alloc(fd: BorrowedFd<'_>, len: usize) -> io::Result<OwnedFd> {
let mut data = dma_heap_allocation_data {
len: len as u64,
fd_flags: OFlags::union(OFlags::CLOEXEC, OFlags::RDWR).bits(),
..dma_heap_allocation_data::default()
};
dma_heap_alloc_ioctl(fd, &mut data)?;
let fd = unsafe {
#[allow(
clippy::cast_possible_wrap,
reason = "The sign doesn't matter, the fd is an opaque value anyway."
)]
OwnedFd::from_raw_fd(data.fd as RawFd)
};
Ok(fd)
}