13da5c369Sopenharmony_ci//! Provide helpers for making ioctl system calls.
23da5c369Sopenharmony_ci//!
33da5c369Sopenharmony_ci//! This library is pretty low-level and messy. `ioctl` is not fun.
43da5c369Sopenharmony_ci//!
53da5c369Sopenharmony_ci//! What is an `ioctl`?
63da5c369Sopenharmony_ci//! ===================
73da5c369Sopenharmony_ci//!
83da5c369Sopenharmony_ci//! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want to add a new
93da5c369Sopenharmony_ci//! syscall? Make it an `ioctl`! `ioctl` refers to both the syscall, and the commands that can be
103da5c369Sopenharmony_ci//! sent with it. `ioctl` stands for "IO control", and the commands are always sent to a file
113da5c369Sopenharmony_ci//! descriptor.
123da5c369Sopenharmony_ci//!
133da5c369Sopenharmony_ci//! It is common to see `ioctl`s used for the following purposes:
143da5c369Sopenharmony_ci//!
153da5c369Sopenharmony_ci//!   * Provide read/write access to out-of-band data related to a device such as configuration
163da5c369Sopenharmony_ci//!     (for instance, setting serial port options)
173da5c369Sopenharmony_ci//!   * Provide a mechanism for performing full-duplex data transfers (for instance, xfer on SPI
183da5c369Sopenharmony_ci//!     devices).
193da5c369Sopenharmony_ci//!   * Provide access to control functions on a device (for example, on Linux you can send
203da5c369Sopenharmony_ci//!     commands like pause, resume, and eject to the CDROM device.
213da5c369Sopenharmony_ci//!   * Do whatever else the device driver creator thought made most sense.
223da5c369Sopenharmony_ci//!
233da5c369Sopenharmony_ci//! `ioctl`s are synchronous system calls and are similar to read and write calls in that regard.
243da5c369Sopenharmony_ci//! They operate on file descriptors and have an identifier that specifies what the ioctl is.
253da5c369Sopenharmony_ci//! Additionally they may read or write data and therefore need to pass along a data pointer.
263da5c369Sopenharmony_ci//! Besides the semantics of the ioctls being confusing, the generation of this identifer can also
273da5c369Sopenharmony_ci//! be difficult.
283da5c369Sopenharmony_ci//!
293da5c369Sopenharmony_ci//! Historically `ioctl` numbers were arbitrary hard-coded values. In Linux (before 2.6) and some
303da5c369Sopenharmony_ci//! unices this has changed to a more-ordered system where the ioctl numbers are partitioned into
313da5c369Sopenharmony_ci//! subcomponents (For linux this is documented in
323da5c369Sopenharmony_ci//! [`Documentation/ioctl/ioctl-number.rst`](https://elixir.bootlin.com/linux/latest/source/Documentation/userspace-api/ioctl/ioctl-number.rst)):
333da5c369Sopenharmony_ci//!
343da5c369Sopenharmony_ci//!   * Number: The actual ioctl ID
353da5c369Sopenharmony_ci//!   * Type: A grouping of ioctls for a common purpose or driver
363da5c369Sopenharmony_ci//!   * Size: The size in bytes of the data that will be transferred
373da5c369Sopenharmony_ci//!   * Direction: Whether there is any data and if it's read, write, or both
383da5c369Sopenharmony_ci//!
393da5c369Sopenharmony_ci//! Newer drivers should not generate complete integer identifiers for their `ioctl`s instead
403da5c369Sopenharmony_ci//! preferring to use the 4 components above to generate the final ioctl identifier. Because of
413da5c369Sopenharmony_ci//! how old `ioctl`s are, however, there are many hard-coded `ioctl` identifiers. These are
423da5c369Sopenharmony_ci//! commonly referred to as "bad" in `ioctl` documentation.
433da5c369Sopenharmony_ci//!
443da5c369Sopenharmony_ci//! Defining `ioctl`s
453da5c369Sopenharmony_ci//! =================
463da5c369Sopenharmony_ci//!
473da5c369Sopenharmony_ci//! This library provides several `ioctl_*!` macros for binding `ioctl`s. These generate public
483da5c369Sopenharmony_ci//! unsafe functions that can then be used for calling the ioctl. This macro has a few different
493da5c369Sopenharmony_ci//! ways it can be used depending on the specific ioctl you're working with.
503da5c369Sopenharmony_ci//!
513da5c369Sopenharmony_ci//! A simple `ioctl` is `SPI_IOC_RD_MODE`. This ioctl works with the SPI interface on Linux. This
523da5c369Sopenharmony_ci//! specific `ioctl` reads the mode of the SPI device as a `u8`. It's declared in
533da5c369Sopenharmony_ci//! `/include/uapi/linux/spi/spidev.h` as `_IOR(SPI_IOC_MAGIC, 1, __u8)`. Since it uses the `_IOR`
543da5c369Sopenharmony_ci//! macro, we know it's a `read` ioctl and can use the `ioctl_read!` macro as follows:
553da5c369Sopenharmony_ci//!
563da5c369Sopenharmony_ci//! ```
573da5c369Sopenharmony_ci//! # #[macro_use] extern crate nix;
583da5c369Sopenharmony_ci//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
593da5c369Sopenharmony_ci//! const SPI_IOC_TYPE_MODE: u8 = 1;
603da5c369Sopenharmony_ci//! ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8);
613da5c369Sopenharmony_ci//! # fn main() {}
623da5c369Sopenharmony_ci//! ```
633da5c369Sopenharmony_ci//!
643da5c369Sopenharmony_ci//! This generates the function:
653da5c369Sopenharmony_ci//!
663da5c369Sopenharmony_ci//! ```
673da5c369Sopenharmony_ci//! # #[macro_use] extern crate nix;
683da5c369Sopenharmony_ci//! # use std::mem;
693da5c369Sopenharmony_ci//! # use nix::{libc, Result};
703da5c369Sopenharmony_ci//! # use nix::errno::Errno;
713da5c369Sopenharmony_ci//! # use nix::libc::c_int as c_int;
723da5c369Sopenharmony_ci//! # const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
733da5c369Sopenharmony_ci//! # const SPI_IOC_TYPE_MODE: u8 = 1;
743da5c369Sopenharmony_ci//! pub unsafe fn spi_read_mode(fd: c_int, data: *mut u8) -> Result<c_int> {
753da5c369Sopenharmony_ci//!     let res = libc::ioctl(fd, request_code_read!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::<u8>()), data);
763da5c369Sopenharmony_ci//!     Errno::result(res)
773da5c369Sopenharmony_ci//! }
783da5c369Sopenharmony_ci//! # fn main() {}
793da5c369Sopenharmony_ci//! ```
803da5c369Sopenharmony_ci//!
813da5c369Sopenharmony_ci//! The return value for the wrapper functions generated by the `ioctl_*!` macros are `nix::Error`s.
823da5c369Sopenharmony_ci//! These are generated by assuming the return value of the ioctl is `-1` on error and everything
833da5c369Sopenharmony_ci//! else is a valid return value. If this is not the case, `Result::map` can be used to map some
843da5c369Sopenharmony_ci//! of the range of "good" values (-Inf..-2, 0..Inf) into a smaller range in a helper function.
853da5c369Sopenharmony_ci//!
863da5c369Sopenharmony_ci//! Writing `ioctl`s generally use pointers as their data source and these should use the
873da5c369Sopenharmony_ci//! `ioctl_write_ptr!`. But in some cases an `int` is passed directly. For these `ioctl`s use the
883da5c369Sopenharmony_ci//! `ioctl_write_int!` macro. This variant does not take a type as the last argument:
893da5c369Sopenharmony_ci//!
903da5c369Sopenharmony_ci//! ```
913da5c369Sopenharmony_ci//! # #[macro_use] extern crate nix;
923da5c369Sopenharmony_ci//! const HCI_IOC_MAGIC: u8 = b'k';
933da5c369Sopenharmony_ci//! const HCI_IOC_HCIDEVUP: u8 = 1;
943da5c369Sopenharmony_ci//! ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
953da5c369Sopenharmony_ci//! # fn main() {}
963da5c369Sopenharmony_ci//! ```
973da5c369Sopenharmony_ci//!
983da5c369Sopenharmony_ci//! Some `ioctl`s don't transfer any data, and those should use `ioctl_none!`. This macro
993da5c369Sopenharmony_ci//! doesn't take a type and so it is declared similar to the `write_int` variant shown above.
1003da5c369Sopenharmony_ci//!
1013da5c369Sopenharmony_ci//! The mode for a given `ioctl` should be clear from the documentation if it has good
1023da5c369Sopenharmony_ci//! documentation. Otherwise it will be clear based on the macro used to generate the `ioctl`
1033da5c369Sopenharmony_ci//! number where `_IO`, `_IOR`, `_IOW`, and `_IOWR` map to "none", "read", "write_*", and "readwrite"
1043da5c369Sopenharmony_ci//! respectively. To determine the specific `write_` variant to use you'll need to find
1053da5c369Sopenharmony_ci//! what the argument type is supposed to be. If it's an `int`, then `write_int` should be used,
1063da5c369Sopenharmony_ci//! otherwise it should be a pointer and `write_ptr` should be used. On Linux the
1073da5c369Sopenharmony_ci//! [`ioctl_list` man page](https://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a
1083da5c369Sopenharmony_ci//! large number of `ioctl`s and describes their argument data type.
1093da5c369Sopenharmony_ci//!
1103da5c369Sopenharmony_ci//! Using "bad" `ioctl`s
1113da5c369Sopenharmony_ci//! --------------------
1123da5c369Sopenharmony_ci//!
1133da5c369Sopenharmony_ci//! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of
1143da5c369Sopenharmony_ci//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the
1153da5c369Sopenharmony_ci//! `ioctl_*_bad!` macros. This naming comes from the Linux kernel which refers to these
1163da5c369Sopenharmony_ci//! `ioctl`s as "bad". These are a different variant as they bypass calling the macro that generates
1173da5c369Sopenharmony_ci//! the ioctl number and instead use the defined value directly.
1183da5c369Sopenharmony_ci//!
1193da5c369Sopenharmony_ci//! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor.
1203da5c369Sopenharmony_ci//! It's defined as `0x5401` in `ioctls.h` on Linux and can be implemented as:
1213da5c369Sopenharmony_ci//!
1223da5c369Sopenharmony_ci//! ```
1233da5c369Sopenharmony_ci//! # #[macro_use] extern crate nix;
1243da5c369Sopenharmony_ci//! # #[cfg(any(target_os = "android", target_os = "linux"))]
1253da5c369Sopenharmony_ci//! # use nix::libc::TCGETS as TCGETS;
1263da5c369Sopenharmony_ci//! # #[cfg(any(target_os = "android", target_os = "linux"))]
1273da5c369Sopenharmony_ci//! # use nix::libc::termios as termios;
1283da5c369Sopenharmony_ci//! # #[cfg(any(target_os = "android", target_os = "linux"))]
1293da5c369Sopenharmony_ci//! ioctl_read_bad!(tcgets, TCGETS, termios);
1303da5c369Sopenharmony_ci//! # fn main() {}
1313da5c369Sopenharmony_ci//! ```
1323da5c369Sopenharmony_ci//!
1333da5c369Sopenharmony_ci//! The generated function has the same form as that generated by `ioctl_read!`:
1343da5c369Sopenharmony_ci//!
1353da5c369Sopenharmony_ci//! ```text
1363da5c369Sopenharmony_ci//! pub unsafe fn tcgets(fd: c_int, data: *mut termios) -> Result<c_int>;
1373da5c369Sopenharmony_ci//! ```
1383da5c369Sopenharmony_ci//!
1393da5c369Sopenharmony_ci//! Working with Arrays
1403da5c369Sopenharmony_ci//! -------------------
1413da5c369Sopenharmony_ci//!
1423da5c369Sopenharmony_ci//! Some `ioctl`s work with entire arrays of elements. These are supported by the `ioctl_*_buf`
1433da5c369Sopenharmony_ci//! family of macros: `ioctl_read_buf`, `ioctl_write_buf`, and `ioctl_readwrite_buf`. Note that
1443da5c369Sopenharmony_ci//! there are no "bad" versions for working with buffers. The generated functions include a `len`
1453da5c369Sopenharmony_ci//! argument to specify the number of elements (where the type of each element is specified in the
1463da5c369Sopenharmony_ci//! macro).
1473da5c369Sopenharmony_ci//!
1483da5c369Sopenharmony_ci//! Again looking to the SPI `ioctl`s on Linux for an example, there is a `SPI_IOC_MESSAGE` `ioctl`
1493da5c369Sopenharmony_ci//! that queues up multiple SPI messages by writing an entire array of `spi_ioc_transfer` structs.
1503da5c369Sopenharmony_ci//! `linux/spi/spidev.h` defines a macro to calculate the `ioctl` number like:
1513da5c369Sopenharmony_ci//!
1523da5c369Sopenharmony_ci//! ```C
1533da5c369Sopenharmony_ci//! #define SPI_IOC_MAGIC 'k'
1543da5c369Sopenharmony_ci//! #define SPI_MSGSIZE(N) ...
1553da5c369Sopenharmony_ci//! #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
1563da5c369Sopenharmony_ci//! ```
1573da5c369Sopenharmony_ci//!
1583da5c369Sopenharmony_ci//! The `SPI_MSGSIZE(N)` calculation is already handled by the `ioctl_*!` macros, so all that's
1593da5c369Sopenharmony_ci//! needed to define this `ioctl` is:
1603da5c369Sopenharmony_ci//!
1613da5c369Sopenharmony_ci//! ```
1623da5c369Sopenharmony_ci//! # #[macro_use] extern crate nix;
1633da5c369Sopenharmony_ci//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
1643da5c369Sopenharmony_ci//! const SPI_IOC_TYPE_MESSAGE: u8 = 0;
1653da5c369Sopenharmony_ci//! # pub struct spi_ioc_transfer(u64);
1663da5c369Sopenharmony_ci//! ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
1673da5c369Sopenharmony_ci//! # fn main() {}
1683da5c369Sopenharmony_ci//! ```
1693da5c369Sopenharmony_ci//!
1703da5c369Sopenharmony_ci//! This generates a function like:
1713da5c369Sopenharmony_ci//!
1723da5c369Sopenharmony_ci//! ```
1733da5c369Sopenharmony_ci//! # #[macro_use] extern crate nix;
1743da5c369Sopenharmony_ci//! # use std::mem;
1753da5c369Sopenharmony_ci//! # use nix::{libc, Result};
1763da5c369Sopenharmony_ci//! # use nix::errno::Errno;
1773da5c369Sopenharmony_ci//! # use nix::libc::c_int as c_int;
1783da5c369Sopenharmony_ci//! # const SPI_IOC_MAGIC: u8 = b'k';
1793da5c369Sopenharmony_ci//! # const SPI_IOC_TYPE_MESSAGE: u8 = 0;
1803da5c369Sopenharmony_ci//! # pub struct spi_ioc_transfer(u64);
1813da5c369Sopenharmony_ci//! pub unsafe fn spi_message(fd: c_int, data: &mut [spi_ioc_transfer]) -> Result<c_int> {
1823da5c369Sopenharmony_ci//!     let res = libc::ioctl(fd,
1833da5c369Sopenharmony_ci//!                           request_code_write!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::<spi_ioc_transfer>()),
1843da5c369Sopenharmony_ci//!                           data);
1853da5c369Sopenharmony_ci//!     Errno::result(res)
1863da5c369Sopenharmony_ci//! }
1873da5c369Sopenharmony_ci//! # fn main() {}
1883da5c369Sopenharmony_ci//! ```
1893da5c369Sopenharmony_ci//!
1903da5c369Sopenharmony_ci//! Finding `ioctl` Documentation
1913da5c369Sopenharmony_ci//! -----------------------------
1923da5c369Sopenharmony_ci//!
1933da5c369Sopenharmony_ci//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
1943da5c369Sopenharmony_ci//! of lines defining macros which use `_IO`, `_IOR`, `_IOW`, `_IOC`, and `_IOWR`. Some `ioctl`s are
1953da5c369Sopenharmony_ci//! documented directly in the headers defining their constants, but others have more extensive
1963da5c369Sopenharmony_ci//! documentation in man pages (like termios' `ioctl`s which are in `tty_ioctl(4)`).
1973da5c369Sopenharmony_ci//!
1983da5c369Sopenharmony_ci//! Documenting the Generated Functions
1993da5c369Sopenharmony_ci//! ===================================
2003da5c369Sopenharmony_ci//!
2013da5c369Sopenharmony_ci//! In many cases, users will wish for the functions generated by the `ioctl`
2023da5c369Sopenharmony_ci//! macro to be public and documented. For this reason, the generated functions
2033da5c369Sopenharmony_ci//! are public by default. If you wish to hide the ioctl, you will need to put
2043da5c369Sopenharmony_ci//! them in a private module.
2053da5c369Sopenharmony_ci//!
2063da5c369Sopenharmony_ci//! For documentation, it is possible to use doc comments inside the `ioctl_*!` macros. Here is an
2073da5c369Sopenharmony_ci//! example :
2083da5c369Sopenharmony_ci//!
2093da5c369Sopenharmony_ci//! ```
2103da5c369Sopenharmony_ci//! # #[macro_use] extern crate nix;
2113da5c369Sopenharmony_ci//! # use nix::libc::c_int;
2123da5c369Sopenharmony_ci//! ioctl_read! {
2133da5c369Sopenharmony_ci//!     /// Make the given terminal the controlling terminal of the calling process. The calling
2143da5c369Sopenharmony_ci//!     /// process must be a session leader and not have a controlling terminal already. If the
2153da5c369Sopenharmony_ci//!     /// terminal is already the controlling terminal of a different session group then the
2163da5c369Sopenharmony_ci//!     /// ioctl will fail with **EPERM**, unless the caller is root (more precisely: has the
2173da5c369Sopenharmony_ci//!     /// **CAP_SYS_ADMIN** capability) and arg equals 1, in which case the terminal is stolen
2183da5c369Sopenharmony_ci//!     /// and all processes that had it as controlling terminal lose it.
2193da5c369Sopenharmony_ci//!     tiocsctty, b't', 19, c_int
2203da5c369Sopenharmony_ci//! }
2213da5c369Sopenharmony_ci//!
2223da5c369Sopenharmony_ci//! # fn main() {}
2233da5c369Sopenharmony_ci//! ```
2243da5c369Sopenharmony_ciuse cfg_if::cfg_if;
2253da5c369Sopenharmony_ci
2263da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
2273da5c369Sopenharmony_ci#[macro_use]
2283da5c369Sopenharmony_cimod linux;
2293da5c369Sopenharmony_ci
2303da5c369Sopenharmony_ci#[cfg(any(
2313da5c369Sopenharmony_ci    target_os = "android",
2323da5c369Sopenharmony_ci    target_os = "linux",
2333da5c369Sopenharmony_ci    target_os = "redox"
2343da5c369Sopenharmony_ci))]
2353da5c369Sopenharmony_cipub use self::linux::*;
2363da5c369Sopenharmony_ci
2373da5c369Sopenharmony_ci#[cfg(any(
2383da5c369Sopenharmony_ci    target_os = "dragonfly",
2393da5c369Sopenharmony_ci    target_os = "freebsd",
2403da5c369Sopenharmony_ci    target_os = "illumos",
2413da5c369Sopenharmony_ci    target_os = "ios",
2423da5c369Sopenharmony_ci    target_os = "macos",
2433da5c369Sopenharmony_ci    target_os = "netbsd",
2443da5c369Sopenharmony_ci    target_os = "haiku",
2453da5c369Sopenharmony_ci    target_os = "openbsd"
2463da5c369Sopenharmony_ci))]
2473da5c369Sopenharmony_ci#[macro_use]
2483da5c369Sopenharmony_cimod bsd;
2493da5c369Sopenharmony_ci
2503da5c369Sopenharmony_ci#[cfg(any(
2513da5c369Sopenharmony_ci    target_os = "dragonfly",
2523da5c369Sopenharmony_ci    target_os = "freebsd",
2533da5c369Sopenharmony_ci    target_os = "illumos",
2543da5c369Sopenharmony_ci    target_os = "ios",
2553da5c369Sopenharmony_ci    target_os = "macos",
2563da5c369Sopenharmony_ci    target_os = "netbsd",
2573da5c369Sopenharmony_ci    target_os = "haiku",
2583da5c369Sopenharmony_ci    target_os = "openbsd"
2593da5c369Sopenharmony_ci))]
2603da5c369Sopenharmony_cipub use self::bsd::*;
2613da5c369Sopenharmony_ci
2623da5c369Sopenharmony_ci/// Convert raw ioctl return value to a Nix result
2633da5c369Sopenharmony_ci#[macro_export]
2643da5c369Sopenharmony_ci#[doc(hidden)]
2653da5c369Sopenharmony_cimacro_rules! convert_ioctl_res {
2663da5c369Sopenharmony_ci    ($w:expr) => {{
2673da5c369Sopenharmony_ci        $crate::errno::Errno::result($w)
2683da5c369Sopenharmony_ci    }};
2693da5c369Sopenharmony_ci}
2703da5c369Sopenharmony_ci
2713da5c369Sopenharmony_ci/// Generates a wrapper function for an ioctl that passes no data to the kernel.
2723da5c369Sopenharmony_ci///
2733da5c369Sopenharmony_ci/// The arguments to this macro are:
2743da5c369Sopenharmony_ci///
2753da5c369Sopenharmony_ci/// * The function name
2763da5c369Sopenharmony_ci/// * The ioctl identifier
2773da5c369Sopenharmony_ci/// * The ioctl sequence number
2783da5c369Sopenharmony_ci///
2793da5c369Sopenharmony_ci/// The generated function has the following signature:
2803da5c369Sopenharmony_ci///
2813da5c369Sopenharmony_ci/// ```rust,ignore
2823da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int>
2833da5c369Sopenharmony_ci/// ```
2843da5c369Sopenharmony_ci///
2853da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
2863da5c369Sopenharmony_ci///
2873da5c369Sopenharmony_ci/// # Example
2883da5c369Sopenharmony_ci///
2893da5c369Sopenharmony_ci/// The `videodev2` driver on Linux defines the `log_status` `ioctl` as:
2903da5c369Sopenharmony_ci///
2913da5c369Sopenharmony_ci/// ```C
2923da5c369Sopenharmony_ci/// #define VIDIOC_LOG_STATUS         _IO('V', 70)
2933da5c369Sopenharmony_ci/// ```
2943da5c369Sopenharmony_ci///
2953da5c369Sopenharmony_ci/// This can be implemented in Rust like:
2963da5c369Sopenharmony_ci///
2973da5c369Sopenharmony_ci/// ```no_run
2983da5c369Sopenharmony_ci/// # #[macro_use] extern crate nix;
2993da5c369Sopenharmony_ci/// ioctl_none!(log_status, b'V', 70);
3003da5c369Sopenharmony_ci/// fn main() {}
3013da5c369Sopenharmony_ci/// ```
3023da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
3033da5c369Sopenharmony_cimacro_rules! ioctl_none {
3043da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
3053da5c369Sopenharmony_ci        $(#[$attr])*
3063da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int)
3073da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
3083da5c369Sopenharmony_ci            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_none!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type))
3093da5c369Sopenharmony_ci        }
3103da5c369Sopenharmony_ci    )
3113da5c369Sopenharmony_ci}
3123da5c369Sopenharmony_ci
3133da5c369Sopenharmony_ci/// Generates a wrapper function for a "bad" ioctl that passes no data to the kernel.
3143da5c369Sopenharmony_ci///
3153da5c369Sopenharmony_ci/// The arguments to this macro are:
3163da5c369Sopenharmony_ci///
3173da5c369Sopenharmony_ci/// * The function name
3183da5c369Sopenharmony_ci/// * The ioctl request code
3193da5c369Sopenharmony_ci///
3203da5c369Sopenharmony_ci/// The generated function has the following signature:
3213da5c369Sopenharmony_ci///
3223da5c369Sopenharmony_ci/// ```rust,ignore
3233da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int>
3243da5c369Sopenharmony_ci/// ```
3253da5c369Sopenharmony_ci///
3263da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
3273da5c369Sopenharmony_ci///
3283da5c369Sopenharmony_ci/// # Example
3293da5c369Sopenharmony_ci///
3303da5c369Sopenharmony_ci/// ```no_run
3313da5c369Sopenharmony_ci/// # #[macro_use] extern crate nix;
3323da5c369Sopenharmony_ci/// # use libc::TIOCNXCL;
3333da5c369Sopenharmony_ci/// # use std::fs::File;
3343da5c369Sopenharmony_ci/// # use std::os::unix::io::AsRawFd;
3353da5c369Sopenharmony_ci/// ioctl_none_bad!(tiocnxcl, TIOCNXCL);
3363da5c369Sopenharmony_ci/// fn main() {
3373da5c369Sopenharmony_ci///     let file = File::open("/dev/ttyUSB0").unwrap();
3383da5c369Sopenharmony_ci///     unsafe { tiocnxcl(file.as_raw_fd()) }.unwrap();
3393da5c369Sopenharmony_ci/// }
3403da5c369Sopenharmony_ci/// ```
3413da5c369Sopenharmony_ci// TODO: add an example using request_code_*!()
3423da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
3433da5c369Sopenharmony_cimacro_rules! ioctl_none_bad {
3443da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $nr:expr) => (
3453da5c369Sopenharmony_ci        $(#[$attr])*
3463da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int)
3473da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
3483da5c369Sopenharmony_ci            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
3493da5c369Sopenharmony_ci        }
3503da5c369Sopenharmony_ci    )
3513da5c369Sopenharmony_ci}
3523da5c369Sopenharmony_ci
3533da5c369Sopenharmony_ci/// Generates a wrapper function for an ioctl that reads data from the kernel.
3543da5c369Sopenharmony_ci///
3553da5c369Sopenharmony_ci/// The arguments to this macro are:
3563da5c369Sopenharmony_ci///
3573da5c369Sopenharmony_ci/// * The function name
3583da5c369Sopenharmony_ci/// * The ioctl identifier
3593da5c369Sopenharmony_ci/// * The ioctl sequence number
3603da5c369Sopenharmony_ci/// * The data type passed by this ioctl
3613da5c369Sopenharmony_ci///
3623da5c369Sopenharmony_ci/// The generated function has the following signature:
3633da5c369Sopenharmony_ci///
3643da5c369Sopenharmony_ci/// ```rust,ignore
3653da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
3663da5c369Sopenharmony_ci/// ```
3673da5c369Sopenharmony_ci///
3683da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
3693da5c369Sopenharmony_ci///
3703da5c369Sopenharmony_ci/// # Example
3713da5c369Sopenharmony_ci///
3723da5c369Sopenharmony_ci/// ```
3733da5c369Sopenharmony_ci/// # #[macro_use] extern crate nix;
3743da5c369Sopenharmony_ci/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
3753da5c369Sopenharmony_ci/// const SPI_IOC_TYPE_MODE: u8 = 1;
3763da5c369Sopenharmony_ci/// ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8);
3773da5c369Sopenharmony_ci/// # fn main() {}
3783da5c369Sopenharmony_ci/// ```
3793da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
3803da5c369Sopenharmony_cimacro_rules! ioctl_read {
3813da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
3823da5c369Sopenharmony_ci        $(#[$attr])*
3833da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int,
3843da5c369Sopenharmony_ci                            data: *mut $ty)
3853da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
3863da5c369Sopenharmony_ci            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))
3873da5c369Sopenharmony_ci        }
3883da5c369Sopenharmony_ci    )
3893da5c369Sopenharmony_ci}
3903da5c369Sopenharmony_ci
3913da5c369Sopenharmony_ci/// Generates a wrapper function for a "bad" ioctl that reads data from the kernel.
3923da5c369Sopenharmony_ci///
3933da5c369Sopenharmony_ci/// The arguments to this macro are:
3943da5c369Sopenharmony_ci///
3953da5c369Sopenharmony_ci/// * The function name
3963da5c369Sopenharmony_ci/// * The ioctl request code
3973da5c369Sopenharmony_ci/// * The data type passed by this ioctl
3983da5c369Sopenharmony_ci///
3993da5c369Sopenharmony_ci/// The generated function has the following signature:
4003da5c369Sopenharmony_ci///
4013da5c369Sopenharmony_ci/// ```rust,ignore
4023da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
4033da5c369Sopenharmony_ci/// ```
4043da5c369Sopenharmony_ci///
4053da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
4063da5c369Sopenharmony_ci///
4073da5c369Sopenharmony_ci/// # Example
4083da5c369Sopenharmony_ci///
4093da5c369Sopenharmony_ci/// ```
4103da5c369Sopenharmony_ci/// # #[macro_use] extern crate nix;
4113da5c369Sopenharmony_ci/// # #[cfg(any(target_os = "android", target_os = "linux"))]
4123da5c369Sopenharmony_ci/// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
4133da5c369Sopenharmony_ci/// # fn main() {}
4143da5c369Sopenharmony_ci/// ```
4153da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
4163da5c369Sopenharmony_cimacro_rules! ioctl_read_bad {
4173da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
4183da5c369Sopenharmony_ci        $(#[$attr])*
4193da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int,
4203da5c369Sopenharmony_ci                            data: *mut $ty)
4213da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
4223da5c369Sopenharmony_ci            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
4233da5c369Sopenharmony_ci        }
4243da5c369Sopenharmony_ci    )
4253da5c369Sopenharmony_ci}
4263da5c369Sopenharmony_ci
4273da5c369Sopenharmony_ci/// Generates a wrapper function for an ioctl that writes data through a pointer to the kernel.
4283da5c369Sopenharmony_ci///
4293da5c369Sopenharmony_ci/// The arguments to this macro are:
4303da5c369Sopenharmony_ci///
4313da5c369Sopenharmony_ci/// * The function name
4323da5c369Sopenharmony_ci/// * The ioctl identifier
4333da5c369Sopenharmony_ci/// * The ioctl sequence number
4343da5c369Sopenharmony_ci/// * The data type passed by this ioctl
4353da5c369Sopenharmony_ci///
4363da5c369Sopenharmony_ci/// The generated function has the following signature:
4373da5c369Sopenharmony_ci///
4383da5c369Sopenharmony_ci/// ```rust,ignore
4393da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int>
4403da5c369Sopenharmony_ci/// ```
4413da5c369Sopenharmony_ci///
4423da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
4433da5c369Sopenharmony_ci///
4443da5c369Sopenharmony_ci/// # Example
4453da5c369Sopenharmony_ci///
4463da5c369Sopenharmony_ci/// ```
4473da5c369Sopenharmony_ci/// # #[macro_use] extern crate nix;
4483da5c369Sopenharmony_ci/// # pub struct v4l2_audio {}
4493da5c369Sopenharmony_ci/// ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
4503da5c369Sopenharmony_ci/// # fn main() {}
4513da5c369Sopenharmony_ci/// ```
4523da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
4533da5c369Sopenharmony_cimacro_rules! ioctl_write_ptr {
4543da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
4553da5c369Sopenharmony_ci        $(#[$attr])*
4563da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int,
4573da5c369Sopenharmony_ci                            data: *const $ty)
4583da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
4593da5c369Sopenharmony_ci            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))
4603da5c369Sopenharmony_ci        }
4613da5c369Sopenharmony_ci    )
4623da5c369Sopenharmony_ci}
4633da5c369Sopenharmony_ci
4643da5c369Sopenharmony_ci/// Generates a wrapper function for a "bad" ioctl that writes data through a pointer to the kernel.
4653da5c369Sopenharmony_ci///
4663da5c369Sopenharmony_ci/// The arguments to this macro are:
4673da5c369Sopenharmony_ci///
4683da5c369Sopenharmony_ci/// * The function name
4693da5c369Sopenharmony_ci/// * The ioctl request code
4703da5c369Sopenharmony_ci/// * The data type passed by this ioctl
4713da5c369Sopenharmony_ci///
4723da5c369Sopenharmony_ci/// The generated function has the following signature:
4733da5c369Sopenharmony_ci///
4743da5c369Sopenharmony_ci/// ```rust,ignore
4753da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int>
4763da5c369Sopenharmony_ci/// ```
4773da5c369Sopenharmony_ci///
4783da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
4793da5c369Sopenharmony_ci///
4803da5c369Sopenharmony_ci/// # Example
4813da5c369Sopenharmony_ci///
4823da5c369Sopenharmony_ci/// ```
4833da5c369Sopenharmony_ci/// # #[macro_use] extern crate nix;
4843da5c369Sopenharmony_ci/// # #[cfg(any(target_os = "android", target_os = "linux"))]
4853da5c369Sopenharmony_ci/// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios);
4863da5c369Sopenharmony_ci/// # fn main() {}
4873da5c369Sopenharmony_ci/// ```
4883da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
4893da5c369Sopenharmony_cimacro_rules! ioctl_write_ptr_bad {
4903da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
4913da5c369Sopenharmony_ci        $(#[$attr])*
4923da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int,
4933da5c369Sopenharmony_ci                            data: *const $ty)
4943da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
4953da5c369Sopenharmony_ci            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
4963da5c369Sopenharmony_ci        }
4973da5c369Sopenharmony_ci    )
4983da5c369Sopenharmony_ci}
4993da5c369Sopenharmony_ci
5003da5c369Sopenharmony_cicfg_if! {
5013da5c369Sopenharmony_ci    if #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] {
5023da5c369Sopenharmony_ci        /// Generates a wrapper function for a ioctl that writes an integer to the kernel.
5033da5c369Sopenharmony_ci        ///
5043da5c369Sopenharmony_ci        /// The arguments to this macro are:
5053da5c369Sopenharmony_ci        ///
5063da5c369Sopenharmony_ci        /// * The function name
5073da5c369Sopenharmony_ci        /// * The ioctl identifier
5083da5c369Sopenharmony_ci        /// * The ioctl sequence number
5093da5c369Sopenharmony_ci        ///
5103da5c369Sopenharmony_ci        /// The generated function has the following signature:
5113da5c369Sopenharmony_ci        ///
5123da5c369Sopenharmony_ci        /// ```rust,ignore
5133da5c369Sopenharmony_ci        /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int>
5143da5c369Sopenharmony_ci        /// ```
5153da5c369Sopenharmony_ci        ///
5163da5c369Sopenharmony_ci        /// `nix::sys::ioctl::ioctl_param_type` depends on the OS:
5173da5c369Sopenharmony_ci        /// *   BSD - `libc::c_int`
5183da5c369Sopenharmony_ci        /// *   Linux - `libc::c_ulong`
5193da5c369Sopenharmony_ci        ///
5203da5c369Sopenharmony_ci        /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
5213da5c369Sopenharmony_ci        ///
5223da5c369Sopenharmony_ci        /// # Example
5233da5c369Sopenharmony_ci        ///
5243da5c369Sopenharmony_ci        /// ```
5253da5c369Sopenharmony_ci        /// # #[macro_use] extern crate nix;
5263da5c369Sopenharmony_ci        /// ioctl_write_int!(vt_activate, b'v', 4);
5273da5c369Sopenharmony_ci        /// # fn main() {}
5283da5c369Sopenharmony_ci        /// ```
5293da5c369Sopenharmony_ci        #[macro_export(local_inner_macros)]
5303da5c369Sopenharmony_ci        macro_rules! ioctl_write_int {
5313da5c369Sopenharmony_ci            ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
5323da5c369Sopenharmony_ci                $(#[$attr])*
5333da5c369Sopenharmony_ci                pub unsafe fn $name(fd: $crate::libc::c_int,
5343da5c369Sopenharmony_ci                                    data: $crate::sys::ioctl::ioctl_param_type)
5353da5c369Sopenharmony_ci                                    -> $crate::Result<$crate::libc::c_int> {
5363da5c369Sopenharmony_ci                    convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data))
5373da5c369Sopenharmony_ci                }
5383da5c369Sopenharmony_ci            )
5393da5c369Sopenharmony_ci        }
5403da5c369Sopenharmony_ci    } else {
5413da5c369Sopenharmony_ci        /// Generates a wrapper function for a ioctl that writes an integer to the kernel.
5423da5c369Sopenharmony_ci        ///
5433da5c369Sopenharmony_ci        /// The arguments to this macro are:
5443da5c369Sopenharmony_ci        ///
5453da5c369Sopenharmony_ci        /// * The function name
5463da5c369Sopenharmony_ci        /// * The ioctl identifier
5473da5c369Sopenharmony_ci        /// * The ioctl sequence number
5483da5c369Sopenharmony_ci        ///
5493da5c369Sopenharmony_ci        /// The generated function has the following signature:
5503da5c369Sopenharmony_ci        ///
5513da5c369Sopenharmony_ci        /// ```rust,ignore
5523da5c369Sopenharmony_ci        /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int>
5533da5c369Sopenharmony_ci        /// ```
5543da5c369Sopenharmony_ci        ///
5553da5c369Sopenharmony_ci        /// `nix::sys::ioctl::ioctl_param_type` depends on the OS:
5563da5c369Sopenharmony_ci        /// *   BSD - `libc::c_int`
5573da5c369Sopenharmony_ci        /// *   Linux - `libc::c_ulong`
5583da5c369Sopenharmony_ci        ///
5593da5c369Sopenharmony_ci        /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
5603da5c369Sopenharmony_ci        ///
5613da5c369Sopenharmony_ci        /// # Example
5623da5c369Sopenharmony_ci        ///
5633da5c369Sopenharmony_ci        /// ```
5643da5c369Sopenharmony_ci        /// # #[macro_use] extern crate nix;
5653da5c369Sopenharmony_ci        /// const HCI_IOC_MAGIC: u8 = b'k';
5663da5c369Sopenharmony_ci        /// const HCI_IOC_HCIDEVUP: u8 = 1;
5673da5c369Sopenharmony_ci        /// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
5683da5c369Sopenharmony_ci        /// # fn main() {}
5693da5c369Sopenharmony_ci        /// ```
5703da5c369Sopenharmony_ci        #[macro_export(local_inner_macros)]
5713da5c369Sopenharmony_ci        macro_rules! ioctl_write_int {
5723da5c369Sopenharmony_ci            ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
5733da5c369Sopenharmony_ci                $(#[$attr])*
5743da5c369Sopenharmony_ci                pub unsafe fn $name(fd: $crate::libc::c_int,
5753da5c369Sopenharmony_ci                                    data: $crate::sys::ioctl::ioctl_param_type)
5763da5c369Sopenharmony_ci                                    -> $crate::Result<$crate::libc::c_int> {
5773da5c369Sopenharmony_ci                    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))
5783da5c369Sopenharmony_ci                }
5793da5c369Sopenharmony_ci            )
5803da5c369Sopenharmony_ci        }
5813da5c369Sopenharmony_ci    }
5823da5c369Sopenharmony_ci}
5833da5c369Sopenharmony_ci
5843da5c369Sopenharmony_ci/// Generates a wrapper function for a "bad" ioctl that writes an integer to the kernel.
5853da5c369Sopenharmony_ci///
5863da5c369Sopenharmony_ci/// The arguments to this macro are:
5873da5c369Sopenharmony_ci///
5883da5c369Sopenharmony_ci/// * The function name
5893da5c369Sopenharmony_ci/// * The ioctl request code
5903da5c369Sopenharmony_ci///
5913da5c369Sopenharmony_ci/// The generated function has the following signature:
5923da5c369Sopenharmony_ci///
5933da5c369Sopenharmony_ci/// ```rust,ignore
5943da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result<libc::c_int>
5953da5c369Sopenharmony_ci/// ```
5963da5c369Sopenharmony_ci///
5973da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
5983da5c369Sopenharmony_ci///
5993da5c369Sopenharmony_ci/// # Examples
6003da5c369Sopenharmony_ci///
6013da5c369Sopenharmony_ci/// ```
6023da5c369Sopenharmony_ci/// # #[macro_use] extern crate nix;
6033da5c369Sopenharmony_ci/// # #[cfg(any(target_os = "android", target_os = "linux"))]
6043da5c369Sopenharmony_ci/// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK);
6053da5c369Sopenharmony_ci/// # fn main() {}
6063da5c369Sopenharmony_ci/// ```
6073da5c369Sopenharmony_ci///
6083da5c369Sopenharmony_ci/// ```rust
6093da5c369Sopenharmony_ci/// # #[macro_use] extern crate nix;
6103da5c369Sopenharmony_ci/// const KVMIO: u8 = 0xAE;
6113da5c369Sopenharmony_ci/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
6123da5c369Sopenharmony_ci/// # fn main() {}
6133da5c369Sopenharmony_ci/// ```
6143da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
6153da5c369Sopenharmony_cimacro_rules! ioctl_write_int_bad {
6163da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $nr:expr) => (
6173da5c369Sopenharmony_ci        $(#[$attr])*
6183da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int,
6193da5c369Sopenharmony_ci                            data: $crate::libc::c_int)
6203da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
6213da5c369Sopenharmony_ci            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
6223da5c369Sopenharmony_ci        }
6233da5c369Sopenharmony_ci    )
6243da5c369Sopenharmony_ci}
6253da5c369Sopenharmony_ci
6263da5c369Sopenharmony_ci/// Generates a wrapper function for an ioctl that reads and writes data to the kernel.
6273da5c369Sopenharmony_ci///
6283da5c369Sopenharmony_ci/// The arguments to this macro are:
6293da5c369Sopenharmony_ci///
6303da5c369Sopenharmony_ci/// * The function name
6313da5c369Sopenharmony_ci/// * The ioctl identifier
6323da5c369Sopenharmony_ci/// * The ioctl sequence number
6333da5c369Sopenharmony_ci/// * The data type passed by this ioctl
6343da5c369Sopenharmony_ci///
6353da5c369Sopenharmony_ci/// The generated function has the following signature:
6363da5c369Sopenharmony_ci///
6373da5c369Sopenharmony_ci/// ```rust,ignore
6383da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
6393da5c369Sopenharmony_ci/// ```
6403da5c369Sopenharmony_ci///
6413da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
6423da5c369Sopenharmony_ci///
6433da5c369Sopenharmony_ci/// # Example
6443da5c369Sopenharmony_ci///
6453da5c369Sopenharmony_ci/// ```
6463da5c369Sopenharmony_ci/// # #[macro_use] extern crate nix;
6473da5c369Sopenharmony_ci/// # pub struct v4l2_audio {}
6483da5c369Sopenharmony_ci/// ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio);
6493da5c369Sopenharmony_ci/// # fn main() {}
6503da5c369Sopenharmony_ci/// ```
6513da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
6523da5c369Sopenharmony_cimacro_rules! ioctl_readwrite {
6533da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
6543da5c369Sopenharmony_ci        $(#[$attr])*
6553da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int,
6563da5c369Sopenharmony_ci                            data: *mut $ty)
6573da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
6583da5c369Sopenharmony_ci            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))
6593da5c369Sopenharmony_ci        }
6603da5c369Sopenharmony_ci    )
6613da5c369Sopenharmony_ci}
6623da5c369Sopenharmony_ci
6633da5c369Sopenharmony_ci/// Generates a wrapper function for a "bad" ioctl that reads and writes data to the kernel.
6643da5c369Sopenharmony_ci///
6653da5c369Sopenharmony_ci/// The arguments to this macro are:
6663da5c369Sopenharmony_ci///
6673da5c369Sopenharmony_ci/// * The function name
6683da5c369Sopenharmony_ci/// * The ioctl request code
6693da5c369Sopenharmony_ci/// * The data type passed by this ioctl
6703da5c369Sopenharmony_ci///
6713da5c369Sopenharmony_ci/// The generated function has the following signature:
6723da5c369Sopenharmony_ci///
6733da5c369Sopenharmony_ci/// ```rust,ignore
6743da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
6753da5c369Sopenharmony_ci/// ```
6763da5c369Sopenharmony_ci///
6773da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
6783da5c369Sopenharmony_ci// TODO: Find an example for ioctl_readwrite_bad
6793da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
6803da5c369Sopenharmony_cimacro_rules! ioctl_readwrite_bad {
6813da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
6823da5c369Sopenharmony_ci        $(#[$attr])*
6833da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int,
6843da5c369Sopenharmony_ci                            data: *mut $ty)
6853da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
6863da5c369Sopenharmony_ci            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
6873da5c369Sopenharmony_ci        }
6883da5c369Sopenharmony_ci    )
6893da5c369Sopenharmony_ci}
6903da5c369Sopenharmony_ci
6913da5c369Sopenharmony_ci/// Generates a wrapper function for an ioctl that reads an array of elements from the kernel.
6923da5c369Sopenharmony_ci///
6933da5c369Sopenharmony_ci/// The arguments to this macro are:
6943da5c369Sopenharmony_ci///
6953da5c369Sopenharmony_ci/// * The function name
6963da5c369Sopenharmony_ci/// * The ioctl identifier
6973da5c369Sopenharmony_ci/// * The ioctl sequence number
6983da5c369Sopenharmony_ci/// * The data type passed by this ioctl
6993da5c369Sopenharmony_ci///
7003da5c369Sopenharmony_ci/// The generated function has the following signature:
7013da5c369Sopenharmony_ci///
7023da5c369Sopenharmony_ci/// ```rust,ignore
7033da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int>
7043da5c369Sopenharmony_ci/// ```
7053da5c369Sopenharmony_ci///
7063da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
7073da5c369Sopenharmony_ci// TODO: Find an example for ioctl_read_buf
7083da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
7093da5c369Sopenharmony_cimacro_rules! ioctl_read_buf {
7103da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
7113da5c369Sopenharmony_ci        $(#[$attr])*
7123da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int,
7133da5c369Sopenharmony_ci                            data: &mut [$ty])
7143da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
7153da5c369Sopenharmony_ci            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
7163da5c369Sopenharmony_ci        }
7173da5c369Sopenharmony_ci    )
7183da5c369Sopenharmony_ci}
7193da5c369Sopenharmony_ci
7203da5c369Sopenharmony_ci/// Generates a wrapper function for an ioctl that writes an array of elements to the kernel.
7213da5c369Sopenharmony_ci///
7223da5c369Sopenharmony_ci/// The arguments to this macro are:
7233da5c369Sopenharmony_ci///
7243da5c369Sopenharmony_ci/// * The function name
7253da5c369Sopenharmony_ci/// * The ioctl identifier
7263da5c369Sopenharmony_ci/// * The ioctl sequence number
7273da5c369Sopenharmony_ci/// * The data type passed by this ioctl
7283da5c369Sopenharmony_ci///
7293da5c369Sopenharmony_ci/// The generated function has the following signature:
7303da5c369Sopenharmony_ci///
7313da5c369Sopenharmony_ci/// ```rust,ignore
7323da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &[DATA_TYPE]) -> Result<libc::c_int>
7333da5c369Sopenharmony_ci/// ```
7343da5c369Sopenharmony_ci///
7353da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
7363da5c369Sopenharmony_ci///
7373da5c369Sopenharmony_ci/// # Examples
7383da5c369Sopenharmony_ci///
7393da5c369Sopenharmony_ci/// ```
7403da5c369Sopenharmony_ci/// # #[macro_use] extern crate nix;
7413da5c369Sopenharmony_ci/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
7423da5c369Sopenharmony_ci/// const SPI_IOC_TYPE_MESSAGE: u8 = 0;
7433da5c369Sopenharmony_ci/// # pub struct spi_ioc_transfer(u64);
7443da5c369Sopenharmony_ci/// ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
7453da5c369Sopenharmony_ci/// # fn main() {}
7463da5c369Sopenharmony_ci/// ```
7473da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
7483da5c369Sopenharmony_cimacro_rules! ioctl_write_buf {
7493da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
7503da5c369Sopenharmony_ci        $(#[$attr])*
7513da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int,
7523da5c369Sopenharmony_ci                            data: &[$ty])
7533da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
7543da5c369Sopenharmony_ci            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
7553da5c369Sopenharmony_ci        }
7563da5c369Sopenharmony_ci    )
7573da5c369Sopenharmony_ci}
7583da5c369Sopenharmony_ci
7593da5c369Sopenharmony_ci/// Generates a wrapper function for an ioctl that reads and writes an array of elements to the kernel.
7603da5c369Sopenharmony_ci///
7613da5c369Sopenharmony_ci/// The arguments to this macro are:
7623da5c369Sopenharmony_ci///
7633da5c369Sopenharmony_ci/// * The function name
7643da5c369Sopenharmony_ci/// * The ioctl identifier
7653da5c369Sopenharmony_ci/// * The ioctl sequence number
7663da5c369Sopenharmony_ci/// * The data type passed by this ioctl
7673da5c369Sopenharmony_ci///
7683da5c369Sopenharmony_ci/// The generated function has the following signature:
7693da5c369Sopenharmony_ci///
7703da5c369Sopenharmony_ci/// ```rust,ignore
7713da5c369Sopenharmony_ci/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int>
7723da5c369Sopenharmony_ci/// ```
7733da5c369Sopenharmony_ci///
7743da5c369Sopenharmony_ci/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
7753da5c369Sopenharmony_ci// TODO: Find an example for readwrite_buf
7763da5c369Sopenharmony_ci#[macro_export(local_inner_macros)]
7773da5c369Sopenharmony_cimacro_rules! ioctl_readwrite_buf {
7783da5c369Sopenharmony_ci    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
7793da5c369Sopenharmony_ci        $(#[$attr])*
7803da5c369Sopenharmony_ci        pub unsafe fn $name(fd: $crate::libc::c_int,
7813da5c369Sopenharmony_ci                            data: &mut [$ty])
7823da5c369Sopenharmony_ci                            -> $crate::Result<$crate::libc::c_int> {
7833da5c369Sopenharmony_ci            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
7843da5c369Sopenharmony_ci        }
7853da5c369Sopenharmony_ci    )
7863da5c369Sopenharmony_ci}
787