1 | //! |
2 | //! Foreign function interface |
3 | //! |
4 | |
5 | #![warn (missing_docs)] |
6 | #![allow (unused_doc_comments)] |
7 | |
8 | pub use drm_sys::{self, *}; |
9 | |
10 | #[macro_use ] |
11 | pub(crate) mod utils; |
12 | |
13 | pub mod gem; |
14 | mod ioctl; |
15 | pub mod mode; |
16 | pub mod syncobj; |
17 | |
18 | use 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 | /// |
27 | pub 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. |
61 | pub 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. |
88 | pub 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 = 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. |
109 | pub fn get_client(fd: BorrowedFd<'_>, idx: c_int) -> io::Result<drm_client> { |
110 | let mut client: drm_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. |
123 | pub fn get_capability(fd: BorrowedFd<'_>, cty: u64) -> io::Result<drm_get_cap> { |
124 | let mut cap: drm_get_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. |
137 | pub fn set_capability(fd: BorrowedFd<'_>, cty: u64, val: bool) -> io::Result<drm_set_client_cap> { |
138 | let cap: drm_set_client_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 |
151 | pub fn set_version(fd: BorrowedFd<'_>, version: &mut drm_set_version) -> io::Result<()> { |
152 | unsafe { ioctl::set_version(fd, data:version) } |
153 | } |
154 | |
155 | /// Gets the driver version for this device. |
156 | pub 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 { ioctl::get_version(fd, &mut sizes) }?; |
164 | |
165 | map_reserve!(name_buf, sizes.name_len as usize); |
166 | map_reserve!(date_buf, sizes.date_len as usize); |
167 | map_reserve!(desc_buf, sizes.desc_len as usize); |
168 | |
169 | let mut version = drm_version { |
170 | name_len: map_len!(&name_buf), |
171 | name: map_ptr!(&name_buf), |
172 | date_len: map_len!(&date_buf), |
173 | date: map_ptr!(&date_buf), |
174 | desc_len: map_len!(&desc_buf), |
175 | desc: map_ptr!(&desc_buf), |
176 | ..Default::default() |
177 | }; |
178 | |
179 | unsafe { ioctl::get_version(fd, &mut version) }?; |
180 | |
181 | map_set!(name_buf, version.name_len as usize); |
182 | map_set!(date_buf, version.date_len as usize); |
183 | map_set!(desc_buf, version.desc_len as usize); |
184 | |
185 | Ok(version) |
186 | } |
187 | |
188 | /// Waits for a vblank. |
189 | pub fn wait_vblank( |
190 | fd: BorrowedFd<'_>, |
191 | type_: u32, |
192 | sequence: u32, |
193 | signal: usize, |
194 | ) -> io::Result<drm_wait_vblank_reply> { |
195 | // We can't assume the kernel will completely fill the reply in the union |
196 | // with valid data (it won't populate the timestamp if the event flag is |
197 | // set, for example), so use `default` to ensure the structure is completely |
198 | // initialized with zeros |
199 | let mut wait_vblank: drm_wait_vblank = drm_wait_vblank::default(); |
200 | wait_vblank.request = drm_wait_vblank_request { |
201 | type_, |
202 | sequence, |
203 | signal: signal as c_ulong, |
204 | }; |
205 | |
206 | unsafe { |
207 | ioctl::wait_vblank(fd, &mut wait_vblank)?; |
208 | }; |
209 | |
210 | Ok(unsafe { wait_vblank.reply }) |
211 | } |
212 | |