linux-ioctl 0.2.1

Helpers for invoking `ioctl`s
Documentation
# `linux-ioctl`

Simple porting tools for Linux-style `ioctl(2)` driver interfaces.

## Motivation

I mainly wrote this crate because I was unhappy with the alternatives:

- `libc::ioctl`
  - The raw `ioctl` function provides no built-in error conversion and requires knowing the `ioctl` request number.
  - `libc` does provide `const fn`s that mirror the `_IOx` macros, but they are only exposed on Linux and have no type safety.
- `nix::ioctl_X!`
  - Looks nothing like the `ioctl` definitions found in C headers.
  - Requires very frequent conscious `nix` updates because it publishes *A LOT* of breaking changes.
- Other crates for this are either abandoned or also frequently publish breaking changes that I'd have to consciously migrate to.
  - Instead, I want a crate that tries to *only* cover `ioctl`s, and has a decently designed API that doesn't see much breakage.
- Almost none of these alternatives except `libc` make translation of C headers to Rust very easy.
  - The Rust code required to do the thing often looks completely different to the equivalent C definitions.
  - As `ioctl`s are a low-level interface often accessed by directly porting a C header, it is beneficial if the result is easy to visually compare to the original C code.

Thus, this library was born in an attempt to address these problems.

## Example

Let's use `uinput` to create a userspace input device.

From `linux/uinput.h`:

```c
/* ioctl */
#define UINPUT_IOCTL_BASE	'U'
#define UI_DEV_CREATE		_IO(UINPUT_IOCTL_BASE, 1)
#define UI_DEV_DESTROY		_IO(UINPUT_IOCTL_BASE, 2)
...
#define UI_DEV_SETUP _IOW(UINPUT_IOCTL_BASE, 3, struct uinput_setup)
```

```rust
use std::{mem, fs::File, ffi::c_char};
use libc::uinput_setup;
use linux_ioctl::{Ioctl, _IO, _IOW};

const UINPUT_IOCTL_BASE: u8 = b'U';
const UI_DEV_CREATE: Ioctl  = _IO(UINPUT_IOCTL_BASE, 1);
const UI_DEV_DESTROY: Ioctl = _IO(UINPUT_IOCTL_BASE, 2);
const UI_DEV_SETUP: Ioctl<*const uinput_setup> = _IOW(UINPUT_IOCTL_BASE, 3);

let uinput = File::options().write(true).open("/dev/uinput")?;

let mut setup: libc::uinput_setup = unsafe { mem::zeroed() };
setup.name[0] = b'A' as c_char; // (must not be blank)
unsafe {
    UI_DEV_SETUP.ioctl(&uinput, &setup)?;
    UI_DEV_CREATE.ioctl(&uinput)?;
    // ...use the device...
    UI_DEV_DESTROY.ioctl(&uinput)?;
}
std::io::Result::Ok(())
```

## Rust Support

This library targets the latest Rust version.

Older Rust versions are supported by equally older versions of this crate. For example, to use a
version of Rust that was succeeded 6 months ago, you'd also use an at least 6 month old version of
this library.

Compatibility with older Rust versions may be provided on a best-effort basis.