drm_ffi/
lib.rs

1//!
2//! Foreign function interface
3//!
4
5#![warn(missing_docs)]
6#![allow(unused_doc_comments)]
7
8pub use drm_sys::{self, *};
9
10#[macro_use]
11pub(crate) mod utils;
12
13pub mod gem;
14mod ioctl;
15pub mod mode;
16pub mod syncobj;
17
18use std::{
19    ffi::{c_int, c_ulong},
20    io,
21    os::unix::io::BorrowedFd,
22};
23
24///
25/// Bindings to the methods of authentication the DRM provides.
26///
27pub mod auth {
28    use crate::ioctl;
29    use drm_sys::*;
30
31    use std::{io, os::unix::io::BorrowedFd};
32
33    /// Get the 'Magic Authentication Token' for this file descriptor.
34    pub fn get_magic_token(fd: BorrowedFd<'_>) -> io::Result<drm_auth> {
35        unsafe { ioctl::get_token(fd) }
36    }
37
38    /// Authorize another process' 'Magic Authentication Token'.
39    pub fn auth_magic_token(fd: BorrowedFd<'_>, auth: u32) -> io::Result<drm_auth> {
40        let token = drm_auth { magic: auth };
41
42        unsafe {
43            ioctl::auth_token(fd, &token)?;
44        }
45
46        Ok(token)
47    }
48
49    /// Acquire the 'Master DRM Lock' for this file descriptor.
50    pub fn acquire_master(fd: BorrowedFd<'_>) -> io::Result<()> {
51        unsafe { ioctl::acquire_master(fd) }
52    }
53
54    /// Release the 'Master DRM Lock' for this file descriptor.
55    pub fn release_master(fd: BorrowedFd<'_>) -> io::Result<()> {
56        unsafe { ioctl::release_master(fd) }
57    }
58}
59
60/// Load this device's Bus ID into a buffer.
61pub fn get_bus_id(fd: BorrowedFd<'_>, mut buf: Option<&mut Vec<u8>>) -> io::Result<drm_unique> {
62    let mut sizes = drm_unique::default();
63    unsafe {
64        ioctl::get_bus_id(fd, &mut sizes)?;
65    }
66
67    if buf.is_none() {
68        return Ok(sizes);
69    }
70
71    map_reserve!(buf, sizes.unique_len as usize);
72
73    let mut busid = drm_unique {
74        unique_len: sizes.unique_len,
75        unique: map_ptr!(&buf),
76    };
77
78    unsafe {
79        ioctl::get_bus_id(fd, &mut busid)?;
80    }
81
82    map_set!(buf, busid.unique_len as usize);
83
84    Ok(busid)
85}
86
87/// Get a device's IRQ.
88pub fn get_interrupt_from_bus_id(
89    fd: BorrowedFd<'_>,
90    bus: c_int,
91    dev: c_int,
92    func: c_int,
93) -> io::Result<drm_irq_busid> {
94    let mut irq = drm_irq_busid {
95        busnum: bus,
96        devnum: dev,
97        funcnum: func,
98        ..Default::default()
99    };
100
101    unsafe {
102        ioctl::get_irq_from_bus_id(fd, &mut irq)?;
103    }
104
105    Ok(irq)
106}
107
108/// Get client information given a client's ID.
109pub fn get_client(fd: BorrowedFd<'_>, idx: c_int) -> io::Result<drm_client> {
110    let mut client = drm_client {
111        idx,
112        ..Default::default()
113    };
114
115    unsafe {
116        ioctl::get_client(fd, &mut client)?;
117    }
118
119    Ok(client)
120}
121
122/// Check if a capability is set.
123pub fn get_capability(fd: BorrowedFd<'_>, cty: u64) -> io::Result<drm_get_cap> {
124    let mut cap = drm_get_cap {
125        capability: cty,
126        ..Default::default()
127    };
128
129    unsafe {
130        ioctl::get_cap(fd, &mut cap)?;
131    }
132
133    Ok(cap)
134}
135
136/// Attempt to enable/disable a client's capability.
137pub fn set_capability(fd: BorrowedFd<'_>, cty: u64, val: bool) -> io::Result<drm_set_client_cap> {
138    let cap = drm_set_client_cap {
139        capability: cty,
140        value: val as u64,
141    };
142
143    unsafe {
144        ioctl::set_cap(fd, &cap)?;
145    }
146
147    Ok(cap)
148}
149
150/// Sets the requested interface version
151pub fn set_version(fd: BorrowedFd<'_>, version: &mut drm_set_version) -> io::Result<()> {
152    unsafe { ioctl::set_version(fd, version) }
153}
154
155/// Gets the driver version for this device.
156pub fn get_version(
157    fd: BorrowedFd<'_>,
158    mut name_buf: Option<&mut Vec<i8>>,
159    mut date_buf: Option<&mut Vec<i8>>,
160    mut desc_buf: Option<&mut Vec<i8>>,
161) -> io::Result<drm_version> {
162    let mut sizes = drm_version::default();
163    unsafe {
164        ioctl::get_version(fd, &mut sizes)?;
165    }
166
167    map_reserve!(name_buf, sizes.name_len as usize);
168    map_reserve!(date_buf, sizes.date_len as usize);
169    map_reserve!(desc_buf, sizes.desc_len as usize);
170
171    let mut version = drm_version {
172        name_len: map_len!(&name_buf),
173        name: map_ptr!(&name_buf),
174        date_len: map_len!(&date_buf),
175        date: map_ptr!(&date_buf),
176        desc_len: map_len!(&desc_buf),
177        desc: map_ptr!(&desc_buf),
178        ..Default::default()
179    };
180
181    unsafe {
182        ioctl::get_version(fd, &mut version)?;
183    }
184
185    map_set!(name_buf, version.name_len as usize);
186    map_set!(date_buf, version.date_len as usize);
187    map_set!(desc_buf, version.desc_len as usize);
188
189    Ok(version)
190}
191
192/// Waits for a vblank.
193pub fn wait_vblank(
194    fd: BorrowedFd<'_>,
195    type_: u32,
196    sequence: u32,
197    signal: usize,
198) -> io::Result<drm_wait_vblank_reply> {
199    // We can't assume the kernel will completely fill the reply in the union
200    // with valid data (it won't populate the timestamp if the event flag is
201    // set, for example), so use `default` to ensure the structure is completely
202    // initialized with zeros
203    let mut wait_vblank = drm_wait_vblank::default();
204    wait_vblank.request = drm_wait_vblank_request {
205        type_,
206        sequence,
207        signal: signal as c_ulong,
208    };
209
210    unsafe {
211        ioctl::wait_vblank(fd, &mut wait_vblank)?;
212    };
213
214    Ok(unsafe { wait_vblank.reply })
215}