| //! |
| //! 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<drm_auth> { |
| unsafe { ioctl::get_token(fd) } |
| } |
| |
| /// Authorize another process' 'Magic Authentication Token'. |
| pub fn auth_magic_token(fd: BorrowedFd<'_>, auth: u32) -> io::Result<drm_auth> { |
| 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<u8>>) -> io::Result<drm_unique> { |
| 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<drm_irq_busid> { |
| 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<drm_client> { |
| 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<drm_get_cap> { |
| 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<drm_set_client_cap> { |
| 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<i8>>, |
| mut date_buf: Option<&mut Vec<i8>>, |
| mut desc_buf: Option<&mut Vec<i8>>, |
| ) -> io::Result<drm_version> { |
| 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<drm_wait_vblank_reply> { |
| // 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 }) |
| } |