Module nix::sys::ioctl
[−]
[src]
Provide helpers for making ioctl system calls
Currently supports Linux on all architectures. Other platforms welcome!
This library is pretty low-level and messy. ioctl
is not fun.
What is an ioctl
?
The ioctl
syscall is the grab-bag syscall on POSIX systems. Don't want
to add a new syscall? Make it an ioctl
! ioctl
refers to both the syscall,
and the commands that can be send with it. ioctl
stands for "IO control",
and the commands are always sent to a file descriptor.
It is common to see ioctl
s used for the following purposes:
- Provide read/write access to out-of-band data related to a device such as configuration (for instance, setting serial port options)
- Provide a mechanism for performing full-duplex data transfers (for instance, xfer on SPI devices).
- Provide access to control functions on a device (for example, on Linux you can send commands like pause, resume, and eject to the CDROM device.
- Do whatever else the device driver creator thought made most sense.
ioctl
s are synchronous system calls and are similar to read and
write calls in that regard.
What does this module support?
This library provides the ioctl!
macro, for binding ioctl
s.
Here's a few examples of how that can work for SPI under Linux
from rust-spidev.
#[macro_use] extern crate nix; #[allow(non_camel_case_types)] pub struct spi_ioc_transfer { pub tx_buf: u64, pub rx_buf: u64, pub len: u32, // optional overrides pub speed_hz: u32, pub delay_usecs: u16, pub bits_per_word: u8, pub cs_change: u8, pub pad: u32, } #[cfg(linux)] mod ioctl { use super::*; const SPI_IOC_MAGIC: u8 = 'k' as u8; const SPI_IOC_NR_TRANSFER: u8 = 0; const SPI_IOC_NR_MODE: u8 = 1; const SPI_IOC_NR_LSB_FIRST: u8 = 2; const SPI_IOC_NR_BITS_PER_WORD: u8 = 3; const SPI_IOC_NR_MAX_SPEED_HZ: u8 = 4; const SPI_IOC_NR_MODE32: u8 = 5; ioctl!(read get_mode_u8 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u8); ioctl!(read get_mode_u32 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u32); ioctl!(write set_mode_u8 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u8); ioctl!(write set_mode_u32 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE32; u32); ioctl!(read get_lsb_first with SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST; u8); ioctl!(write set_lsb_first with SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST; u8); ioctl!(read get_bits_per_word with SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD; u8); ioctl!(write set_bits_per_word with SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD; u8); ioctl!(read get_max_speed_hz with SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ; u32); ioctl!(write set_max_speed_hz with SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ; u32); ioctl!(write spidev_transfer with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer); ioctl!(write buf spidev_transfer_buf with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer); } // doctest workaround fn main() {}
Spidev uses the _IOC
macros that are encouraged (as far as
ioctl
can be encouraged at all) for newer drivers. Many
drivers, however, just use magic numbers with no attached
semantics. For those, the ioctl!(bad ...)
variant should be
used (the "bad" terminology is from the Linux kernel).
How do I get the magic numbers?
For Linux, look at your system's headers. For example, /usr/include/linxu/input.h
has a lot
of lines defining macros which use _IOR
, _IOW
, _IOC
, and _IORW
. These macros
correspond to the ior!
, iow!
, ioc!
, and iorw!
macros defined in this crate.
Additionally, there is the ioctl!
macro for creating a wrapper around ioctl
that is
somewhat more type-safe.
Most ioctl
s have no or little documentation. You'll need to scrounge through
the source to figure out what they do and how they should be used.