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 ioctls used for the following purposes:

ioctls 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 ioctls. 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 ioctls 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.