diff options
-rw-r--r-- | src/sys/ioctl/mod.rs | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/src/sys/ioctl/mod.rs b/src/sys/ioctl/mod.rs index a4e51cbd..94018521 100644 --- a/src/sys/ioctl/mod.rs +++ b/src/sys/ioctl/mod.rs @@ -30,13 +30,61 @@ //! What does this module support? //! =============================== //! -//! This library provides the `ioctl!` macro, for binding `ioctl`s. It also tries -//! to bind every `ioctl` supported by the system with said macro, but -//! some `ioctl`s requires some amount of manual work (usually by -//! providing `struct` declaration) that this library does not support yet. -//! -//! Additionally, in `etc`, there are scripts for scraping system headers for -//! `ioctl` definitions, and generating calls to `ioctl!` corresponding to them. +//! 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](https://github.com/posborne/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, +//! } +//! +//! 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? //! =============================== @@ -50,28 +98,6 @@ //! 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. //! -//! # Interface Overview -//! -//! This ioctl module seeks to tame the ioctl beast by providing a set of safer (although not safe) -//! functions implementing the most common ioctl access patterns. -//! -//! The most common access patterns for ioctls are as follows: -//! -//! 1. `read`: A pointer is provided to the kernel which is populated -//! with a value containing the "result" of the operation. The -//! result may be an integer or structure. The kernel may also -//! read values from the provided pointer (usually a structure). -//! 2. `write`: A pointer is provided to the kernel containing values -//! that the kernel will read in order to perform the operation. -//! 3. `execute`: The operation is passed to the kernel but no -//! additional pointer is passed. The operation is enough -//! and it either succeeds or results in an error. -//! -//! Where appropriate, versions of these interface function are provided -//! taking either refernces or pointers. The pointer versions are -//! necessary for cases (notably slices) where a reference cannot -//! be generically cast to a pointer. - #[cfg(any(target_os = "linux", target_os = "android"))] #[path = "platform/linux.rs"] #[macro_use] |