1 | //! Provide helpers for making ioctl system calls. |
2 | //! |
3 | //! This library is pretty low-level and messy. `ioctl` is not fun. |
4 | //! |
5 | //! What is an `ioctl`? |
6 | //! =================== |
7 | //! |
8 | //! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want to add a new |
9 | //! syscall? Make it an `ioctl`! `ioctl` refers to both the syscall, and the commands that can be |
10 | //! sent with it. `ioctl` stands for "IO control", and the commands are always sent to a file |
11 | //! descriptor. |
12 | //! |
13 | //! It is common to see `ioctl`s used for the following purposes: |
14 | //! |
15 | //! * Provide read/write access to out-of-band data related to a device such as configuration |
16 | //! (for instance, setting serial port options) |
17 | //! * Provide a mechanism for performing full-duplex data transfers (for instance, xfer on SPI |
18 | //! devices). |
19 | //! * Provide access to control functions on a device (for example, on Linux you can send |
20 | //! commands like pause, resume, and eject to the CDROM device. |
21 | //! * Do whatever else the device driver creator thought made most sense. |
22 | //! |
23 | //! `ioctl`s are synchronous system calls and are similar to read and write calls in that regard. |
24 | //! They operate on file descriptors and have an identifier that specifies what the ioctl is. |
25 | //! Additionally they may read or write data and therefore need to pass along a data pointer. |
26 | //! Besides the semantics of the ioctls being confusing, the generation of this identifer can also |
27 | //! be difficult. |
28 | //! |
29 | //! Historically `ioctl` numbers were arbitrary hard-coded values. In Linux (before 2.6) and some |
30 | //! unices this has changed to a more-ordered system where the ioctl numbers are partitioned into |
31 | //! subcomponents (For linux this is documented in |
32 | //! [`Documentation/ioctl/ioctl-number.rst`](https://elixir.bootlin.com/linux/latest/source/Documentation/userspace-api/ioctl/ioctl-number.rst)): |
33 | //! |
34 | //! * Number: The actual ioctl ID |
35 | //! * Type: A grouping of ioctls for a common purpose or driver |
36 | //! * Size: The size in bytes of the data that will be transferred |
37 | //! * Direction: Whether there is any data and if it's read, write, or both |
38 | //! |
39 | //! Newer drivers should not generate complete integer identifiers for their `ioctl`s instead |
40 | //! preferring to use the 4 components above to generate the final ioctl identifier. Because of |
41 | //! how old `ioctl`s are, however, there are many hard-coded `ioctl` identifiers. These are |
42 | //! commonly referred to as "bad" in `ioctl` documentation. |
43 | //! |
44 | //! Defining `ioctl`s |
45 | //! ================= |
46 | //! |
47 | //! This library provides several `ioctl_*!` macros for binding `ioctl`s. These generate public |
48 | //! unsafe functions that can then be used for calling the ioctl. This macro has a few different |
49 | //! ways it can be used depending on the specific ioctl you're working with. |
50 | //! |
51 | //! A simple `ioctl` is `SPI_IOC_RD_MODE`. This ioctl works with the SPI interface on Linux. This |
52 | //! specific `ioctl` reads the mode of the SPI device as a `u8`. It's declared in |
53 | //! `/include/uapi/linux/spi/spidev.h` as `_IOR(SPI_IOC_MAGIC, 1, __u8)`. Since it uses the `_IOR` |
54 | //! macro, we know it's a `read` ioctl and can use the `ioctl_read!` macro as follows: |
55 | //! |
56 | //! ``` |
57 | //! # #[macro_use ] extern crate nix; |
58 | //! const SPI_IOC_MAGIC: u8 = b'k' ; // Defined in linux/spi/spidev.h |
59 | //! const SPI_IOC_TYPE_MODE: u8 = 1; |
60 | //! ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8); |
61 | //! # fn main() {} |
62 | //! ``` |
63 | //! |
64 | //! This generates the function: |
65 | //! |
66 | //! ``` |
67 | //! # #[macro_use ] extern crate nix; |
68 | //! # use std::mem; |
69 | //! # use nix::{libc, Result}; |
70 | //! # use nix::errno::Errno; |
71 | //! # use nix::libc::c_int as c_int; |
72 | //! # const SPI_IOC_MAGIC: u8 = b'k' ; // Defined in linux/spi/spidev.h |
73 | //! # const SPI_IOC_TYPE_MODE: u8 = 1; |
74 | //! pub unsafe fn spi_read_mode(fd: c_int, data: *mut u8) -> Result<c_int> { |
75 | //! let res = libc::ioctl(fd, request_code_read!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::<u8>()), data); |
76 | //! Errno::result(res) |
77 | //! } |
78 | //! # fn main() {} |
79 | //! ``` |
80 | //! |
81 | //! The return value for the wrapper functions generated by the `ioctl_*!` macros are `nix::Error`s. |
82 | //! These are generated by assuming the return value of the ioctl is `-1` on error and everything |
83 | //! else is a valid return value. If this is not the case, `Result::map` can be used to map some |
84 | //! of the range of "good" values (-Inf..-2, 0..Inf) into a smaller range in a helper function. |
85 | //! |
86 | //! Writing `ioctl`s generally use pointers as their data source and these should use the |
87 | //! `ioctl_write_ptr!`. But in some cases an `int` is passed directly. For these `ioctl`s use the |
88 | //! `ioctl_write_int!` macro. This variant does not take a type as the last argument: |
89 | //! |
90 | //! ``` |
91 | //! # #[macro_use ] extern crate nix; |
92 | //! const HCI_IOC_MAGIC: u8 = b'k' ; |
93 | //! const HCI_IOC_HCIDEVUP: u8 = 1; |
94 | //! ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP); |
95 | //! # fn main() {} |
96 | //! ``` |
97 | //! |
98 | //! Some `ioctl`s don't transfer any data, and those should use `ioctl_none!`. This macro |
99 | //! doesn't take a type and so it is declared similar to the `write_int` variant shown above. |
100 | //! |
101 | //! The mode for a given `ioctl` should be clear from the documentation if it has good |
102 | //! documentation. Otherwise it will be clear based on the macro used to generate the `ioctl` |
103 | //! number where `_IO`, `_IOR`, `_IOW`, and `_IOWR` map to "none", "read", "write_*", and "readwrite" |
104 | //! respectively. To determine the specific `write_` variant to use you'll need to find |
105 | //! what the argument type is supposed to be. If it's an `int`, then `write_int` should be used, |
106 | //! otherwise it should be a pointer and `write_ptr` should be used. On Linux the |
107 | //! [`ioctl_list` man page](https://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a |
108 | //! large number of `ioctl`s and describes their argument data type. |
109 | //! |
110 | //! Using "bad" `ioctl`s |
111 | //! -------------------- |
112 | //! |
113 | //! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of |
114 | //! generating `ioctl` numbers and instead use hardcoded values. These can be used with the |
115 | //! `ioctl_*_bad!` macros. This naming comes from the Linux kernel which refers to these |
116 | //! `ioctl`s as "bad". These are a different variant as they bypass calling the macro that generates |
117 | //! the ioctl number and instead use the defined value directly. |
118 | //! |
119 | //! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor. |
120 | //! It's defined as `0x5401` in `ioctls.h` on Linux and can be implemented as: |
121 | //! |
122 | //! ``` |
123 | //! # #[macro_use ] extern crate nix; |
124 | //! # #[cfg (any(target_os = "android" , target_os = "linux" ))] |
125 | //! # use nix::libc::TCGETS as TCGETS; |
126 | //! # #[cfg (any(target_os = "android" , target_os = "linux" ))] |
127 | //! # use nix::libc::termios as termios; |
128 | //! # #[cfg (any(target_os = "android" , target_os = "linux" ))] |
129 | //! ioctl_read_bad!(tcgets, TCGETS, termios); |
130 | //! # fn main() {} |
131 | //! ``` |
132 | //! |
133 | //! The generated function has the same form as that generated by `ioctl_read!`: |
134 | //! |
135 | //! ```text |
136 | //! pub unsafe fn tcgets(fd: c_int, data: *mut termios) -> Result<c_int>; |
137 | //! ``` |
138 | //! |
139 | //! Working with Arrays |
140 | //! ------------------- |
141 | //! |
142 | //! Some `ioctl`s work with entire arrays of elements. These are supported by the `ioctl_*_buf` |
143 | //! family of macros: `ioctl_read_buf`, `ioctl_write_buf`, and `ioctl_readwrite_buf`. Note that |
144 | //! there are no "bad" versions for working with buffers. The generated functions include a `len` |
145 | //! argument to specify the number of elements (where the type of each element is specified in the |
146 | //! macro). |
147 | //! |
148 | //! Again looking to the SPI `ioctl`s on Linux for an example, there is a `SPI_IOC_MESSAGE` `ioctl` |
149 | //! that queues up multiple SPI messages by writing an entire array of `spi_ioc_transfer` structs. |
150 | //! `linux/spi/spidev.h` defines a macro to calculate the `ioctl` number like: |
151 | //! |
152 | //! ```C |
153 | //! #define SPI_IOC_MAGIC 'k' |
154 | //! #define SPI_MSGSIZE(N) ... |
155 | //! #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) |
156 | //! ``` |
157 | //! |
158 | //! The `SPI_MSGSIZE(N)` calculation is already handled by the `ioctl_*!` macros, so all that's |
159 | //! needed to define this `ioctl` is: |
160 | //! |
161 | //! ``` |
162 | //! # #[macro_use ] extern crate nix; |
163 | //! const SPI_IOC_MAGIC: u8 = b'k' ; // Defined in linux/spi/spidev.h |
164 | //! const SPI_IOC_TYPE_MESSAGE: u8 = 0; |
165 | //! # pub struct spi_ioc_transfer(u64); |
166 | //! ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer); |
167 | //! # fn main() {} |
168 | //! ``` |
169 | //! |
170 | //! This generates a function like: |
171 | //! |
172 | //! ``` |
173 | //! # #[macro_use ] extern crate nix; |
174 | //! # use std::mem; |
175 | //! # use nix::{libc, Result}; |
176 | //! # use nix::errno::Errno; |
177 | //! # use nix::libc::c_int as c_int; |
178 | //! # const SPI_IOC_MAGIC: u8 = b'k' ; |
179 | //! # const SPI_IOC_TYPE_MESSAGE: u8 = 0; |
180 | //! # pub struct spi_ioc_transfer(u64); |
181 | //! pub unsafe fn spi_message(fd: c_int, data: &mut [spi_ioc_transfer]) -> Result<c_int> { |
182 | //! let res = libc::ioctl(fd, |
183 | //! request_code_write!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::<spi_ioc_transfer>()), |
184 | //! data); |
185 | //! Errno::result(res) |
186 | //! } |
187 | //! # fn main() {} |
188 | //! ``` |
189 | //! |
190 | //! Finding `ioctl` Documentation |
191 | //! ----------------------------- |
192 | //! |
193 | //! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot |
194 | //! of lines defining macros which use `_IO`, `_IOR`, `_IOW`, `_IOC`, and `_IOWR`. Some `ioctl`s are |
195 | //! documented directly in the headers defining their constants, but others have more extensive |
196 | //! documentation in man pages (like termios' `ioctl`s which are in `tty_ioctl(4)`). |
197 | //! |
198 | //! Documenting the Generated Functions |
199 | //! =================================== |
200 | //! |
201 | //! In many cases, users will wish for the functions generated by the `ioctl` |
202 | //! macro to be public and documented. For this reason, the generated functions |
203 | //! are public by default. If you wish to hide the ioctl, you will need to put |
204 | //! them in a private module. |
205 | //! |
206 | //! For documentation, it is possible to use doc comments inside the `ioctl_*!` macros. Here is an |
207 | //! example : |
208 | //! |
209 | //! ``` |
210 | //! # #[macro_use ] extern crate nix; |
211 | //! # use nix::libc::c_int; |
212 | //! ioctl_read! { |
213 | //! /// Make the given terminal the controlling terminal of the calling process. The calling |
214 | //! /// process must be a session leader and not have a controlling terminal already. If the |
215 | //! /// terminal is already the controlling terminal of a different session group then the |
216 | //! /// ioctl will fail with **EPERM**, unless the caller is root (more precisely: has the |
217 | //! /// **CAP_SYS_ADMIN** capability) and arg equals 1, in which case the terminal is stolen |
218 | //! /// and all processes that had it as controlling terminal lose it. |
219 | //! tiocsctty, b't' , 19, c_int |
220 | //! } |
221 | //! |
222 | //! # fn main() {} |
223 | //! ``` |
224 | use cfg_if::cfg_if; |
225 | |
226 | #[cfg (any(target_os = "android" , target_os = "linux" , target_os = "redox" ))] |
227 | #[macro_use ] |
228 | mod linux; |
229 | |
230 | #[cfg (any( |
231 | target_os = "android" , |
232 | target_os = "linux" , |
233 | target_os = "redox" |
234 | ))] |
235 | pub use self::linux::*; |
236 | |
237 | #[cfg (any( |
238 | target_os = "dragonfly" , |
239 | target_os = "freebsd" , |
240 | target_os = "illumos" , |
241 | target_os = "ios" , |
242 | target_os = "macos" , |
243 | target_os = "netbsd" , |
244 | target_os = "haiku" , |
245 | target_os = "openbsd" |
246 | ))] |
247 | #[macro_use ] |
248 | mod bsd; |
249 | |
250 | #[cfg (any( |
251 | target_os = "dragonfly" , |
252 | target_os = "freebsd" , |
253 | target_os = "illumos" , |
254 | target_os = "ios" , |
255 | target_os = "macos" , |
256 | target_os = "netbsd" , |
257 | target_os = "haiku" , |
258 | target_os = "openbsd" |
259 | ))] |
260 | pub use self::bsd::*; |
261 | |
262 | /// Convert raw ioctl return value to a Nix result |
263 | #[macro_export ] |
264 | #[doc (hidden)] |
265 | macro_rules! convert_ioctl_res { |
266 | ($w:expr) => {{ |
267 | $crate::errno::Errno::result($w) |
268 | }}; |
269 | } |
270 | |
271 | /// Generates a wrapper function for an ioctl that passes no data to the kernel. |
272 | /// |
273 | /// The arguments to this macro are: |
274 | /// |
275 | /// * The function name |
276 | /// * The ioctl identifier |
277 | /// * The ioctl sequence number |
278 | /// |
279 | /// The generated function has the following signature: |
280 | /// |
281 | /// ```rust,ignore |
282 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int> |
283 | /// ``` |
284 | /// |
285 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
286 | /// |
287 | /// # Example |
288 | /// |
289 | /// The `videodev2` driver on Linux defines the `log_status` `ioctl` as: |
290 | /// |
291 | /// ```C |
292 | /// #define VIDIOC_LOG_STATUS _IO('V', 70) |
293 | /// ``` |
294 | /// |
295 | /// This can be implemented in Rust like: |
296 | /// |
297 | /// ```no_run |
298 | /// # #[macro_use ] extern crate nix; |
299 | /// ioctl_none!(log_status, b'V' , 70); |
300 | /// fn main() {} |
301 | /// ``` |
302 | #[macro_export (local_inner_macros)] |
303 | macro_rules! ioctl_none { |
304 | ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => ( |
305 | $(#[$attr])* |
306 | pub unsafe fn $name(fd: $crate::libc::c_int) |
307 | -> $crate::Result<$crate::libc::c_int> { |
308 | convert_ioctl_res!($crate::libc::ioctl(fd, request_code_none!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type)) |
309 | } |
310 | ) |
311 | } |
312 | |
313 | /// Generates a wrapper function for a "bad" ioctl that passes no data to the kernel. |
314 | /// |
315 | /// The arguments to this macro are: |
316 | /// |
317 | /// * The function name |
318 | /// * The ioctl request code |
319 | /// |
320 | /// The generated function has the following signature: |
321 | /// |
322 | /// ```rust,ignore |
323 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int> |
324 | /// ``` |
325 | /// |
326 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
327 | /// |
328 | /// # Example |
329 | /// |
330 | /// ```no_run |
331 | /// # #[macro_use ] extern crate nix; |
332 | /// # use libc::TIOCNXCL; |
333 | /// # use std::fs::File; |
334 | /// # use std::os::unix::io::AsRawFd; |
335 | /// ioctl_none_bad!(tiocnxcl, TIOCNXCL); |
336 | /// fn main() { |
337 | /// let file = File::open("/dev/ttyUSB0" ).unwrap(); |
338 | /// unsafe { tiocnxcl(file.as_raw_fd()) }.unwrap(); |
339 | /// } |
340 | /// ``` |
341 | // TODO: add an example using request_code_*!() |
342 | #[macro_export (local_inner_macros)] |
343 | macro_rules! ioctl_none_bad { |
344 | ($(#[$attr:meta])* $name:ident, $nr:expr) => ( |
345 | $(#[$attr])* |
346 | pub unsafe fn $name(fd: $crate::libc::c_int) |
347 | -> $crate::Result<$crate::libc::c_int> { |
348 | convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type)) |
349 | } |
350 | ) |
351 | } |
352 | |
353 | /// Generates a wrapper function for an ioctl that reads data from the kernel. |
354 | /// |
355 | /// The arguments to this macro are: |
356 | /// |
357 | /// * The function name |
358 | /// * The ioctl identifier |
359 | /// * The ioctl sequence number |
360 | /// * The data type passed by this ioctl |
361 | /// |
362 | /// The generated function has the following signature: |
363 | /// |
364 | /// ```rust,ignore |
365 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int> |
366 | /// ``` |
367 | /// |
368 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
369 | /// |
370 | /// # Example |
371 | /// |
372 | /// ``` |
373 | /// # #[macro_use ] extern crate nix; |
374 | /// const SPI_IOC_MAGIC: u8 = b'k' ; // Defined in linux/spi/spidev.h |
375 | /// const SPI_IOC_TYPE_MODE: u8 = 1; |
376 | /// ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8); |
377 | /// # fn main() {} |
378 | /// ``` |
379 | #[macro_export (local_inner_macros)] |
380 | macro_rules! ioctl_read { |
381 | ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( |
382 | $(#[$attr])* |
383 | pub unsafe fn $name(fd: $crate::libc::c_int, |
384 | data: *mut $ty) |
385 | -> $crate::Result<$crate::libc::c_int> { |
386 | convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) |
387 | } |
388 | ) |
389 | } |
390 | |
391 | /// Generates a wrapper function for a "bad" ioctl that reads data from the kernel. |
392 | /// |
393 | /// The arguments to this macro are: |
394 | /// |
395 | /// * The function name |
396 | /// * The ioctl request code |
397 | /// * The data type passed by this ioctl |
398 | /// |
399 | /// The generated function has the following signature: |
400 | /// |
401 | /// ```rust,ignore |
402 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int> |
403 | /// ``` |
404 | /// |
405 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
406 | /// |
407 | /// # Example |
408 | /// |
409 | /// ``` |
410 | /// # #[macro_use ] extern crate nix; |
411 | /// # #[cfg (any(target_os = "android" , target_os = "linux" ))] |
412 | /// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios); |
413 | /// # fn main() {} |
414 | /// ``` |
415 | #[macro_export (local_inner_macros)] |
416 | macro_rules! ioctl_read_bad { |
417 | ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => ( |
418 | $(#[$attr])* |
419 | pub unsafe fn $name(fd: $crate::libc::c_int, |
420 | data: *mut $ty) |
421 | -> $crate::Result<$crate::libc::c_int> { |
422 | convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) |
423 | } |
424 | ) |
425 | } |
426 | |
427 | /// Generates a wrapper function for an ioctl that writes data through a pointer to the kernel. |
428 | /// |
429 | /// The arguments to this macro are: |
430 | /// |
431 | /// * The function name |
432 | /// * The ioctl identifier |
433 | /// * The ioctl sequence number |
434 | /// * The data type passed by this ioctl |
435 | /// |
436 | /// The generated function has the following signature: |
437 | /// |
438 | /// ```rust,ignore |
439 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int> |
440 | /// ``` |
441 | /// |
442 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
443 | /// |
444 | /// # Example |
445 | /// |
446 | /// ``` |
447 | /// # #[macro_use ] extern crate nix; |
448 | /// # pub struct v4l2_audio {} |
449 | /// ioctl_write_ptr!(s_audio, b'V' , 34, v4l2_audio); |
450 | /// # fn main() {} |
451 | /// ``` |
452 | #[macro_export (local_inner_macros)] |
453 | macro_rules! ioctl_write_ptr { |
454 | ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( |
455 | $(#[$attr])* |
456 | pub unsafe fn $name(fd: $crate::libc::c_int, |
457 | data: *const $ty) |
458 | -> $crate::Result<$crate::libc::c_int> { |
459 | convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) |
460 | } |
461 | ) |
462 | } |
463 | |
464 | /// Generates a wrapper function for a "bad" ioctl that writes data through a pointer to the kernel. |
465 | /// |
466 | /// The arguments to this macro are: |
467 | /// |
468 | /// * The function name |
469 | /// * The ioctl request code |
470 | /// * The data type passed by this ioctl |
471 | /// |
472 | /// The generated function has the following signature: |
473 | /// |
474 | /// ```rust,ignore |
475 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int> |
476 | /// ``` |
477 | /// |
478 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
479 | /// |
480 | /// # Example |
481 | /// |
482 | /// ``` |
483 | /// # #[macro_use ] extern crate nix; |
484 | /// # #[cfg (any(target_os = "android" , target_os = "linux" ))] |
485 | /// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios); |
486 | /// # fn main() {} |
487 | /// ``` |
488 | #[macro_export (local_inner_macros)] |
489 | macro_rules! ioctl_write_ptr_bad { |
490 | ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => ( |
491 | $(#[$attr])* |
492 | pub unsafe fn $name(fd: $crate::libc::c_int, |
493 | data: *const $ty) |
494 | -> $crate::Result<$crate::libc::c_int> { |
495 | convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) |
496 | } |
497 | ) |
498 | } |
499 | |
500 | cfg_if! { |
501 | if #[cfg(any(target_os = "dragonfly" , target_os = "freebsd" ))] { |
502 | /// Generates a wrapper function for a ioctl that writes an integer to the kernel. |
503 | /// |
504 | /// The arguments to this macro are: |
505 | /// |
506 | /// * The function name |
507 | /// * The ioctl identifier |
508 | /// * The ioctl sequence number |
509 | /// |
510 | /// The generated function has the following signature: |
511 | /// |
512 | /// ```rust,ignore |
513 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int> |
514 | /// ``` |
515 | /// |
516 | /// `nix::sys::ioctl::ioctl_param_type` depends on the OS: |
517 | /// * BSD - `libc::c_int` |
518 | /// * Linux - `libc::c_ulong` |
519 | /// |
520 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
521 | /// |
522 | /// # Example |
523 | /// |
524 | /// ``` |
525 | /// # #[macro_use] extern crate nix; |
526 | /// ioctl_write_int!(vt_activate, b'v', 4); |
527 | /// # fn main() {} |
528 | /// ``` |
529 | #[macro_export (local_inner_macros)] |
530 | macro_rules! ioctl_write_int { |
531 | ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => ( |
532 | $(#[$attr])* |
533 | pub unsafe fn $name(fd: $crate::libc::c_int, |
534 | data: $crate::sys::ioctl::ioctl_param_type) |
535 | -> $crate::Result<$crate::libc::c_int> { |
536 | convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data)) |
537 | } |
538 | ) |
539 | } |
540 | } else { |
541 | /// Generates a wrapper function for a ioctl that writes an integer to the kernel. |
542 | /// |
543 | /// The arguments to this macro are: |
544 | /// |
545 | /// * The function name |
546 | /// * The ioctl identifier |
547 | /// * The ioctl sequence number |
548 | /// |
549 | /// The generated function has the following signature: |
550 | /// |
551 | /// ```rust,ignore |
552 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int> |
553 | /// ``` |
554 | /// |
555 | /// `nix::sys::ioctl::ioctl_param_type` depends on the OS: |
556 | /// * BSD - `libc::c_int` |
557 | /// * Linux - `libc::c_ulong` |
558 | /// |
559 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
560 | /// |
561 | /// # Example |
562 | /// |
563 | /// ``` |
564 | /// # #[macro_use] extern crate nix; |
565 | /// const HCI_IOC_MAGIC: u8 = b'k'; |
566 | /// const HCI_IOC_HCIDEVUP: u8 = 1; |
567 | /// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP); |
568 | /// # fn main() {} |
569 | /// ``` |
570 | #[macro_export (local_inner_macros)] |
571 | macro_rules! ioctl_write_int { |
572 | ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => ( |
573 | $(#[$attr])* |
574 | pub unsafe fn $name(fd: $crate::libc::c_int, |
575 | data: $crate::sys::ioctl::ioctl_param_type) |
576 | -> $crate::Result<$crate::libc::c_int> { |
577 | convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data)) |
578 | } |
579 | ) |
580 | } |
581 | } |
582 | } |
583 | |
584 | /// Generates a wrapper function for a "bad" ioctl that writes an integer to the kernel. |
585 | /// |
586 | /// The arguments to this macro are: |
587 | /// |
588 | /// * The function name |
589 | /// * The ioctl request code |
590 | /// |
591 | /// The generated function has the following signature: |
592 | /// |
593 | /// ```rust,ignore |
594 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result<libc::c_int> |
595 | /// ``` |
596 | /// |
597 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
598 | /// |
599 | /// # Examples |
600 | /// |
601 | /// ``` |
602 | /// # #[macro_use ] extern crate nix; |
603 | /// # #[cfg (any(target_os = "android" , target_os = "linux" ))] |
604 | /// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK); |
605 | /// # fn main() {} |
606 | /// ``` |
607 | /// |
608 | /// ```rust |
609 | /// # #[macro_use ] extern crate nix; |
610 | /// const KVMIO: u8 = 0xAE; |
611 | /// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03)); |
612 | /// # fn main() {} |
613 | /// ``` |
614 | #[macro_export (local_inner_macros)] |
615 | macro_rules! ioctl_write_int_bad { |
616 | ($(#[$attr:meta])* $name:ident, $nr:expr) => ( |
617 | $(#[$attr])* |
618 | pub unsafe fn $name(fd: $crate::libc::c_int, |
619 | data: $crate::libc::c_int) |
620 | -> $crate::Result<$crate::libc::c_int> { |
621 | convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) |
622 | } |
623 | ) |
624 | } |
625 | |
626 | /// Generates a wrapper function for an ioctl that reads and writes data to the kernel. |
627 | /// |
628 | /// The arguments to this macro are: |
629 | /// |
630 | /// * The function name |
631 | /// * The ioctl identifier |
632 | /// * The ioctl sequence number |
633 | /// * The data type passed by this ioctl |
634 | /// |
635 | /// The generated function has the following signature: |
636 | /// |
637 | /// ```rust,ignore |
638 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int> |
639 | /// ``` |
640 | /// |
641 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
642 | /// |
643 | /// # Example |
644 | /// |
645 | /// ``` |
646 | /// # #[macro_use ] extern crate nix; |
647 | /// # pub struct v4l2_audio {} |
648 | /// ioctl_readwrite!(enum_audio, b'V' , 65, v4l2_audio); |
649 | /// # fn main() {} |
650 | /// ``` |
651 | #[macro_export (local_inner_macros)] |
652 | macro_rules! ioctl_readwrite { |
653 | ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( |
654 | $(#[$attr])* |
655 | pub unsafe fn $name(fd: $crate::libc::c_int, |
656 | data: *mut $ty) |
657 | -> $crate::Result<$crate::libc::c_int> { |
658 | convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) |
659 | } |
660 | ) |
661 | } |
662 | |
663 | /// Generates a wrapper function for a "bad" ioctl that reads and writes data to the kernel. |
664 | /// |
665 | /// The arguments to this macro are: |
666 | /// |
667 | /// * The function name |
668 | /// * The ioctl request code |
669 | /// * The data type passed by this ioctl |
670 | /// |
671 | /// The generated function has the following signature: |
672 | /// |
673 | /// ```rust,ignore |
674 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int> |
675 | /// ``` |
676 | /// |
677 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
678 | // TODO: Find an example for ioctl_readwrite_bad |
679 | #[macro_export (local_inner_macros)] |
680 | macro_rules! ioctl_readwrite_bad { |
681 | ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => ( |
682 | $(#[$attr])* |
683 | pub unsafe fn $name(fd: $crate::libc::c_int, |
684 | data: *mut $ty) |
685 | -> $crate::Result<$crate::libc::c_int> { |
686 | convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) |
687 | } |
688 | ) |
689 | } |
690 | |
691 | /// Generates a wrapper function for an ioctl that reads an array of elements from the kernel. |
692 | /// |
693 | /// The arguments to this macro are: |
694 | /// |
695 | /// * The function name |
696 | /// * The ioctl identifier |
697 | /// * The ioctl sequence number |
698 | /// * The data type passed by this ioctl |
699 | /// |
700 | /// The generated function has the following signature: |
701 | /// |
702 | /// ```rust,ignore |
703 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int> |
704 | /// ``` |
705 | /// |
706 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
707 | // TODO: Find an example for ioctl_read_buf |
708 | #[macro_export (local_inner_macros)] |
709 | macro_rules! ioctl_read_buf { |
710 | ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( |
711 | $(#[$attr])* |
712 | pub unsafe fn $name(fd: $crate::libc::c_int, |
713 | data: &mut [$ty]) |
714 | -> $crate::Result<$crate::libc::c_int> { |
715 | convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data)) |
716 | } |
717 | ) |
718 | } |
719 | |
720 | /// Generates a wrapper function for an ioctl that writes an array of elements to the kernel. |
721 | /// |
722 | /// The arguments to this macro are: |
723 | /// |
724 | /// * The function name |
725 | /// * The ioctl identifier |
726 | /// * The ioctl sequence number |
727 | /// * The data type passed by this ioctl |
728 | /// |
729 | /// The generated function has the following signature: |
730 | /// |
731 | /// ```rust,ignore |
732 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &[DATA_TYPE]) -> Result<libc::c_int> |
733 | /// ``` |
734 | /// |
735 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
736 | /// |
737 | /// # Examples |
738 | /// |
739 | /// ``` |
740 | /// # #[macro_use ] extern crate nix; |
741 | /// const SPI_IOC_MAGIC: u8 = b'k' ; // Defined in linux/spi/spidev.h |
742 | /// const SPI_IOC_TYPE_MESSAGE: u8 = 0; |
743 | /// # pub struct spi_ioc_transfer(u64); |
744 | /// ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer); |
745 | /// # fn main() {} |
746 | /// ``` |
747 | #[macro_export (local_inner_macros)] |
748 | macro_rules! ioctl_write_buf { |
749 | ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( |
750 | $(#[$attr])* |
751 | pub unsafe fn $name(fd: $crate::libc::c_int, |
752 | data: &[$ty]) |
753 | -> $crate::Result<$crate::libc::c_int> { |
754 | convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data)) |
755 | } |
756 | ) |
757 | } |
758 | |
759 | /// Generates a wrapper function for an ioctl that reads and writes an array of elements to the kernel. |
760 | /// |
761 | /// The arguments to this macro are: |
762 | /// |
763 | /// * The function name |
764 | /// * The ioctl identifier |
765 | /// * The ioctl sequence number |
766 | /// * The data type passed by this ioctl |
767 | /// |
768 | /// The generated function has the following signature: |
769 | /// |
770 | /// ```rust,ignore |
771 | /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int> |
772 | /// ``` |
773 | /// |
774 | /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). |
775 | // TODO: Find an example for readwrite_buf |
776 | #[macro_export (local_inner_macros)] |
777 | macro_rules! ioctl_readwrite_buf { |
778 | ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( |
779 | $(#[$attr])* |
780 | pub unsafe fn $name(fd: $crate::libc::c_int, |
781 | data: &mut [$ty]) |
782 | -> $crate::Result<$crate::libc::c_int> { |
783 | convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data)) |
784 | } |
785 | ) |
786 | } |
787 | |