Function _IOW

Source
pub const fn _IOW<T>(ty: u8, nr: u8) -> Ioctl<*const T>
Expand description

Creates an Ioctl that writes data of type T to the kernel.

By default, a pointer to the data will be passed to ioctl(2), and the kernel will read the argument from that location. This is generally correct if the argument is a struct, but if the argument is a primitive type like int, or is already a pointer like char*, many drivers expect the argument to be passed to ioctl(2) without indirection. To bind to those ioctls, you can call Ioctl::with_direct_arg on the Ioctl returned by _IOW.

§Errors

This method will cause a compile-time assertion failure if the size of T exceeds the ioctl argument size limit. This typically means that the wrong type T was specified.

§Example

Let’s create a virtual input device with uinput.

From linux/uinput.h:

/* 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)
...
#define UI_SET_EVBIT		_IOW(UINPUT_IOCTL_BASE, 100, int)
#define UI_SET_KEYBIT		_IOW(UINPUT_IOCTL_BASE, 101, int)

From linux/input.h:

#define EV_KEY			0x01
...
#define KEY_A			30
use std::{mem, fs::File, ffi::{c_char, c_int}};
use libc::uinput_setup;
use linux_ioctl::*;

const UINPUT_IOCTL_BASE: u8 = b'U';
const UI_DEV_CREATE: Ioctl<NoArgs> = _IO(UINPUT_IOCTL_BASE, 1);
const UI_DEV_DESTROY: Ioctl<NoArgs> = _IO(UINPUT_IOCTL_BASE, 2);
const UI_DEV_SETUP: Ioctl<*const uinput_setup> = _IOW(UINPUT_IOCTL_BASE, 3);
// These two expect their argument to be passed directly instead of behind a pointer:
const UI_SET_EVBIT: Ioctl<c_int> = _IOW(UINPUT_IOCTL_BASE, 100).with_direct_arg();
const UI_SET_KEYBIT: Ioctl<c_int> = _IOW(UINPUT_IOCTL_BASE, 101).with_direct_arg();

const EV_KEY: c_int = 0x01;
const KEY_A: c_int = 30;

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

// Enable the "A" key:
unsafe {
    UI_SET_EVBIT.ioctl(&uinput, EV_KEY)?;
    UI_SET_KEYBIT.ioctl(&uinput, KEY_A)?;
}

let mut setup: 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)?;
}