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//! ```
224use cfg_if::cfg_if;
225
226#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
227#[macro_use]
228mod linux;
229
230#[cfg(any(
231 target_os = "android",
232 target_os = "linux",
233 target_os = "redox"
234))]
235pub 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]
248mod 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))]
260pub use self::bsd::*;
261
262/// Convert raw ioctl return value to a Nix result
263#[macro_export]
264#[doc(hidden)]
265macro_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)]
303macro_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)]
343macro_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)]
380macro_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)]
416macro_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)]
453macro_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)]
489macro_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
500cfg_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)]
615macro_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)]
652macro_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)]
680macro_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)]
709macro_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)]
748macro_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)]
777macro_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