//! //! Foreign function interface //! #![warn(missing_docs)] #![allow(unused_doc_comments)] pub use drm_sys::{self, *}; #[macro_use] pub(crate) mod utils; pub mod gem; mod ioctl; pub mod mode; pub mod syncobj; use std::{ ffi::{c_int, c_ulong}, io, os::unix::io::BorrowedFd, }; /// /// Bindings to the methods of authentication the DRM provides. /// pub mod auth { use crate::ioctl; use drm_sys::*; use std::{io, os::unix::io::BorrowedFd}; /// Get the 'Magic Authentication Token' for this file descriptor. pub fn get_magic_token(fd: BorrowedFd<'_>) -> io::Result { unsafe { ioctl::get_token(fd) } } /// Authorize another process' 'Magic Authentication Token'. pub fn auth_magic_token(fd: BorrowedFd<'_>, auth: u32) -> io::Result { let token = drm_auth { magic: auth }; unsafe { ioctl::auth_token(fd, &token)?; } Ok(token) } /// Acquire the 'Master DRM Lock' for this file descriptor. pub fn acquire_master(fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { ioctl::acquire_master(fd) } } /// Release the 'Master DRM Lock' for this file descriptor. pub fn release_master(fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { ioctl::release_master(fd) } } } /// Load this device's Bus ID into a buffer. 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, &mut sizes)?; } if buf.is_none() { return Ok(sizes); } map_reserve!(buf, sizes.unique_len as usize); let mut busid = drm_unique { unique_len: sizes.unique_len, unique: map_ptr!(&buf), }; unsafe { ioctl::get_bus_id(fd, &mut busid)?; } map_set!(buf, busid.unique_len as usize); Ok(busid) } /// Get a device's IRQ. pub fn get_interrupt_from_bus_id( fd: BorrowedFd<'_>, bus: c_int, dev: c_int, func: c_int, ) -> io::Result { let mut irq = drm_irq_busid { busnum: bus, devnum: dev, funcnum: func, ..Default::default() }; unsafe { ioctl::get_irq_from_bus_id(fd, &mut irq)?; } Ok(irq) } /// Get client information given a client's ID. pub fn get_client(fd: BorrowedFd<'_>, idx: c_int) -> io::Result { let mut client = drm_client { idx, ..Default::default() }; unsafe { ioctl::get_client(fd, &mut client)?; } Ok(client) } /// Check if a capability is set. pub fn get_capability(fd: BorrowedFd<'_>, cty: u64) -> io::Result { let mut cap = drm_get_cap { capability: cty, ..Default::default() }; unsafe { ioctl::get_cap(fd, &mut cap)?; } Ok(cap) } /// Attempt to enable/disable a client's capability. pub fn set_capability(fd: BorrowedFd<'_>, cty: u64, val: bool) -> io::Result { let cap = drm_set_client_cap { capability: cty, value: val as u64, }; unsafe { ioctl::set_cap(fd, &cap)?; } Ok(cap) } /// Sets the requested interface version pub fn set_version(fd: BorrowedFd<'_>, version: &mut drm_set_version) -> io::Result<()> { unsafe { ioctl::set_version(fd, version) } } /// Gets the driver version for this device. pub fn get_version( fd: BorrowedFd<'_>, mut name_buf: Option<&mut Vec>, mut date_buf: Option<&mut Vec>, mut desc_buf: Option<&mut Vec>, ) -> io::Result { let mut sizes = drm_version::default(); unsafe { ioctl::get_version(fd, &mut sizes)?; } map_reserve!(name_buf, sizes.name_len as usize); map_reserve!(date_buf, sizes.date_len as usize); map_reserve!(desc_buf, sizes.desc_len as usize); let mut version = drm_version { name_len: map_len!(&name_buf), name: map_ptr!(&name_buf), date_len: map_len!(&date_buf), date: map_ptr!(&date_buf), desc_len: map_len!(&desc_buf), desc: map_ptr!(&desc_buf), ..Default::default() }; unsafe { ioctl::get_version(fd, &mut version)?; } map_set!(name_buf, version.name_len as usize); map_set!(date_buf, version.date_len as usize); map_set!(desc_buf, version.desc_len as usize); Ok(version) } /// Waits for a vblank. pub fn wait_vblank( fd: BorrowedFd<'_>, type_: u32, sequence: u32, signal: usize, ) -> 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 // initialized with zeros let mut wait_vblank = drm_wait_vblank::default(); wait_vblank.request = drm_wait_vblank_request { type_, sequence, signal: signal as c_ulong, }; unsafe { ioctl::wait_vblank(fd, &mut wait_vblank)?; }; Ok(unsafe { wait_vblank.reply }) }